安装
如果是windows
系统,点击安装SDK:http://www.gekorm.com/dart-windows/
如果是Mac
系统,点击安装SDK:https://dart.dev/get-dart
可将dart
安装后的bin
目录加入到path
路径中,打开命令行工具,使用命令dart --version
确保dart
已安装到您电脑中即可。
为什么要学些这门语言
目前Google
推出的最新跨端解决方案Flutter
,需要采用Dart语言
编写前端代码。Flutter
是目前市面上最好的跨端应用解决方案,另外,Dart语言
学习门槛低性能好,支持动静态编译,并支持很多高级语言特性。
语法要点
dart语言
借鉴了java
,js
,swift
等高级的语言特性,并融入很多使用的语法糖,我们来简要做个概括。
- 在Dart中所有变量引用的都是对象,继承
Object
,包括数字,函数,null
等都是对象; - 在Dart运行之前会解析您的代码,通过使用类型和编译型常量来帮助Dart捕获异常,让代码运行的更高效;
- Dart支持在方法中定义方法,函数是Dart非常重要的概念;
- Dart没有
public
,private
,protected
关键字,如果要申明私有成员变量或函数请使用_打头; - 可以在代码中加入
assert
断言语句以便让有些错误在编译器就能被捕获;
启动入口
Dart语言也是把main函数作为入口程序。可以给main函数传入List
入参来接收命令行参数列表。
内置类型
dart语言
使用var
声明变量,和swift
的id
类似,在编译阶段会自动确认其类型。
dart语言
只有以下几种内置类型:String
,Number
,bool
,Map
,List
,Function
,Symbols
,runes
等,其中Number
分为int
和double
,注意没有float
之类的浮点数类型,可以对Number
类型四则运算,其中取整运算符是~/
,有一些常用的属性,如isNaN,isEven(是否偶数),isOdd(是否奇数)等,可以做一些简单的类型转换,如int.parse("1");double.parse("1.1"
等,注意在Dart中没有数组类型,而统一使用List;
- 字符串:使用
"""
多行字符串声明,可以使用$xx
或${xx}
在字符串中使用变量占位符,相邻的字符串拼接的+
可省略,但拼接的内容不能是1个空格。 - 静态变量:可以使用关键字static修饰类访问的变量。
- Dart字符串是UTF-16 code units字符序列,所以支持emoji表情符,如笑脸: \u{1f600};
类的使用
Dart和Java等高级语言一样,可以定义类,并使用extends
继承类,使用@override
注解声明你要重写的函数,使用super
调用重写这个父类的函数。
如果要在代码尝试使用类中不存在的方法或实例变量检测时做出反应,可以重写noSuchMethod
。
可以使用abstract
修饰符定义无法实例化的类;
一个类可以使用implements
实现多个接口;
可以使用enum
定义枚举;
一个类可以通过..
使用级联调用语法,比如querySelector("#id")..text="xxx"..onClick.listen(xxx);
泛型
泛型有以下好处:
- 减少代码重复:泛型允许您在多种类型之间共享单个接口和实现,同时仍然利用静态分析;
- 代码更友好,编译期提醒:比如列表中的元素指定泛型类型可确保不符合类型的元素被添加;
- 与Java不同,Dart会在运行期携带类型信息,如
List
类型的列表,可以使用lists.runtimeType()
,获取到类型信息List
; - 可以配合
extends
来限定参数类型; - 泛型可以被使用在包括函数,函数表达式,类方法,类型参数,返回类型等中;
重写操作符
我们可以通过关键字operator关键字重写包括:+,-,*,/,<,>,<=,>=,%,/,[],[]=,,=,<<,>>等十几种运算符:
类型自动推断
在声明一个变量时,无需指定类型,系统会自动推断,比如var m= {"a":1};var i=1;
,系统自动认为m
是Map类型
,i
是整型
。如果一个变量被赋值后,在后续会被另外类型的变量值覆写,应该使用dynamic
声明这个变量。
final和const
用来定义常量,都必须初始化,const
是编译时常量,只能用编译时常量来初始化,但final
可以用变量来初始化,比如final time = new DateTime.now();
是允许的。
函数
函数类型是Function,函数可以赋值,也可以作为参数传递给其他函数,这是函数式编程典型特征。在Dart中不能重载函数,函数可以不指定返回类型(实际会返回Object),而实际上函数体可以返回任意类型,如果在函数体中没有return,则返回null。
在我们编写Flutter程序时,经常会碰到函数体只是返回一个布局,那么函数体在一条语句的情况下,可以简写成:void printxx(num n) => print(n);
,注意箭头的用法。
另外函数的参数非常有意思,可指定可选参数(使用{}将可选参数括起来),可以通过:或=指定参数默认值,也可以使用位置参数(用[]括起来),注意位置参数如果有多个,必须跟实际传入的是实参一一对应。
函数可以用来赋值,比如:var uu = (msg) => "'${msg.toUpperCase()}'";
,以上uu是一个函数,将传入的字符串转换成大写,可以直接调用uu("hello")
即返回HELLO
。
函数也可以作为参数,比如Future.delayed(new Duration(seconds: 2),(){return "hi";})
,第二个参数就是一个函数,函数作为参数的用法在Flutter编程中随处可见,是一个非常重要的用法。
构造函数
Dart是不支持函数重载的,那多个构造函数怎么办?我们可以使用命名构造函数,比如Text.a(this.a);Test.ab(this.a,this.b)
等命令构造函数
闭包
一个闭包是一个方法对象,不管该对象在何处被调用, 该对象都可以访问其作用域内的变量。方法可以封闭定义到其作用域内的变量。比如以下代码:
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
main() {
var add2 = makeAdder(2);
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
异步支持
Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数。async和await关键词支持了异步编程,允许您写出和同步代码很像的异步代码。
以上写法在Flutter编程中经常被用到,将异步的调用方式以同步的写法呈现,使得我们理解起来更加直观。
元数据注解
元数据注解以字符开头@
,后跟对编译时常量(如deprecated
)的引用或对常量构造函数的调用。元数据可以出现在库
,类
,typedef
,类型参数
,构造函数
,工厂
,函数
,字段
,参数
或变量声明之前以及导入或导出指令之前。您可以使用反射在运行时检索元数据,所有Dart代码都有两个注解:@deprecated
和 @override
。你可以定义自己的元数据注解,如下:
之后就可以使用注解:
@todo('name','ddd')
。
Mixin
有时候将某些行为定义为Mixin,以便让其他类通过with来实现多重继承,减少代码冗余。比如var CC=T with A,B
,表示CC类中的方法是T,A,B三个类的方法的并集,当有函数名重名的时候,B的方法覆盖A,T的,A方法覆盖T的。这样就变相支持了多重继承。
反射
dart:mirrors 库提供了基本的反射支持。可以通过#打头定义Symbols,这样在代码混交的情况下也可以保持标识符名称。比如你知道类名,可以直接用new Symbol("CLASSNAME")来构建symbol。比如我们动态调用C类的d方法,d方法有一个参数:
class C{
var tt = "test";
C(){};
static d(msg){print(msg);}
a(){print("C.a";)}
}
//调用类的静态函数
ClassMirror cc = reflectClass(C);
cc.invoke(Symbol("d"), ["hello"]);
//如果调用实例函数
InstanceMirror mm = cc.newInstance(Symbol.empty, []);
mm.invoke(Symbol("a"), []);
//获取类的成员变量
print(mm.reflectee.tt);
此外,还可以通过反射获取注解,元数据等,具体可参考:https://www.jianshu.com/p/d68278d19f79
Flutter中禁止使用反射。