logo头像

小玉的技术博客

Dart语言简介

前言

Dart在静态语法方面和Java非常相似,如类型定义、函数声明、泛型等,而在动态特性方面又和JavaScript很像,如函数式特性、异步支持等。除了融合Java和JavaScript语言之所长之外,Dart也具有一些其它具有表现力的语法,如可选命名参数、..(级联运算符)和?.(条件成员访问运算符)以及??(判空赋值运算符)。其实,对编程语言了解比较多的读者会发现,在Dart中其实看到的不仅有Java和JavaScript的影子,它还具有其它编程语言中的身影,如命名参数在Objective-C和Swift中早就很普遍,而??操作符在PHP 7.0语法中就已经存在了,因此我们可以看到Google对Dart语言给予厚望,是想把Dart打造成一门集百家之所长的编程语言。

变量声明

1.var
类似于JavaScript中的var,它可以接收任何类型的变量,但最大的不同是Dart中var变量一旦赋值,类型便会确定,则不能再改变其类型,如:

1
2
3
4
5
var t;
t = "hello world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
// 类型一旦确定后则不能再更改其类型。
t = 20;

上面的代码在JavaScript是没有问题的,前端开发者需要注意一下,之所以有此差异是因为Dart本身是一个强类型语言,任何变量都是有确定类型的,在Dart中,当用var声明一个变量后,Dart在编译时会根据第一次赋值数据的类型来推断其类型,编译结束后其类型就已经被确定,而JavaScript是纯粹的弱类型脚本语言,var只是变量的声明方式而已。
2.dynamic和Object
Object 是Dart所有对象的根基类,也就是说所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象. dynamic与var一样都是关键词,声明的变量可以赋值任意对象。 而dynamic与Object相同之处在于,他们声明的变量可以在后期改变赋值类型。

1
2
3
4
5
6
7
dynamic t;
Object x;
t = "hellow world";
x = 'Hello Object';
//下面代码没有问题
t = 400;
x = 2000;

dynamic与Object不同的是,dynamic声明的对象编译器会提供所有可能的组合, 而Object声明的对象只能使用Object的属性与方法, 否则编译器会报错。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dynamic a;
Object b;
main() {
a = "";
b = "";
printLengths();
}
printLengths() {
// no warning
print(a.length);
// warning:
// The getter 'length' is not defined for the class 'Object'
print(b.length);
}

变量a不会报错, 变量b编译器会报错
dynamic的这个特性与Objective-C中的id作用很像. dynamic的这个特点使得我们在使用它时需要格外注意,这很容易引入一个运行时错误.
3.final和const
如果您从未打算更改一个变量,那么使用 final 或 const,不是var,也不是一个类型。 一个 final 变量只能被设置一次,两者区别在于:const 变量是一个编译时常量,final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略,如:

1
2
3
4
5
//可以省略String这个类型声明
final str = "hello world";
//final String str = "hello world";
const str1 = "hello world";
//const String str1 = "hello world";

函数

Dart是一种真正的面向对象的语言,所以即使是函数也是对象,并且有一个类型Function。这意味着函数可以赋值给变量或作为参数传递给其他函数,这是函数式编程的典型特征。
1.函数声明

1
2
3
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}

Dart函数声明如果没有显式声明返回值类型时会默认当做dynamic处理,注意,函数返回值没有类型推断:

1
2
3
4
5
6
7
8
9
10
11
12
typedef bool CALLBACK();
//不指定返回类型,此时默认为dynamic,不是bool
isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void test(CALLBACK cb){
print(cb());
}
//报错,isNoble不是bool类型
test(isNoble);

2.对于只包含一个表达式的函数,可以使用简写语法

1
bool isNoble (int atomicNumber)=> _nobleGases [ atomicNumber ] != null ;

3.函数作为变量

1
2
3
4
var say = (str){
print(str);
};
say("hello world");

4.函数作为参数传递

1
2
3
4
void execute(var callback) {
callback();
}
execute(() => print("xxx"))

5.可选的位置参数
包装一组函数参数,用[]标记为可选的位置参数,并放在参数列表的最后面:

1
2
3
4
5
6
7
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}

下面是一个不带可选参数调用这个函数的例子:

1
say('one', 'two'); //结果是: one says two

下面是用第三个参数调用这个函数的例子:

1
say('one','two','three');//结果是:one says two with a three

6.可选的命名参数
定义函数时,使用{param1, param2, …},放在参数列表的最后面,用于指定命名参数。例如:

1
2
3
4
//设置[bold]和[hidden]标志
void enableFlags({bool bold, bool hidden}) {
// ...
}

调用函数时,可以使用指定命名参数。例如:paramName: value

1
enableFlags(bold: true, hidden: false);

可选命名参数在Flutter中使用非常多。

注意,不能同时使用可选的位置参数和可选的命名参数

支付宝打赏 微信打赏

赞赏是不耍流氓的鼓励