Dart语法

注释

和Java一样,基础的注释没什么不同的(//、/* */)

Dart中可以使用文档注释符号:///或者/**开头,之后通过dartdoc命令进行文档导出,导出的文档存放于工程根目录/doc/api/中,点击index.html之后就可以看到文档了

变量和常量

变量

声明:var,Object,dynamic

var name = '张三' ;

//如果对象不限于单一类型(没有明确的类型),请使用Object或dynamic关键字
Object name = '张三';
dynamic name = '李四';

在Dart中,一切皆为对象,所以如果我们没有对变量做初始化,默认值为null

常量

常量声明:final、const

一个final变量只能被设置一次,const变量是一个编译时的常量,也可以看作为隐式的final

flnal 或者 const 不能和 var 同时使用

如果常量是类级别的,我们需要使用static const,例如:

static const speed = 100;

const关键字的“妙用”–在某些情况下可以被修改

// 注意: [] 创建的是一个空的list集合
// const []创建一个空的、不可变的列表(EIL)。
var varList = const []; // varList 当前是一个EIL
final finalList = const []; // finalList一直是EIL
const constList = const []; // constList 是一个编译时常量的EIL

// 可以更改非final,非const变量的值
// 即使它曾经具有const值
varList = ["Hello World"];

如果我们对const类型做四则运算将会得到一个const类型的值,例如:

const pi = 3.14
const area = pi * 100 * 100

数据类型

基本数据类型

和Java、kotlin有比较多区别的是:

numbers–数字

runes–字符(用于在字符串中表示unicode字符)

Numbers

num是数字类型的父类,有两个子类int和double

Dart2.1里面新增特性,当double的值为int值时,int自动转成double 例如:

double test = 12;//打印结果是12.0

同时也可以通过许多的to类型的方法来转换数据

int

dart的int取值范围为-2^53~2^53

double

dart中的double是双精度浮点型,也就是64位长度的浮点型数据

String

在Dart中,String类型也可以使用+操作,具体使用方法和Java中一致

我们也可以用三个单引号或者双引号来定义多行的String类型,一般这种用法是用于在Flutter中表示大文本块,例如:

var string1 = '''
这是一个特别特别大的文本。
这个文本可以用来添加多行数据
''';
var string2 = """
这是一个特别特别大的文本。
这个文本可以用来添加多行数据
""";

Boolean

Dart语言是强bool类型检查,只有bool类型的值为true才被人为是true,我们以前可能见过有的语言的0是false,大于0是true,在Dart语言里面不是的

List

在Dart语言中,具有一系列相同类型的数据成为List对象,定义一般是这样定义的:

var list = [1, 2, 3]

List对象的第一个元素的索引也是0,最后一个元素的索引为list.length - 1

Map

Map类型将key和value关联在一起,也就是常说的键值对,key必须是唯一的,我们可以通过以下几种方式创建一个Map

var fruit = {
'apple' : '苹果',
'banana' : '香蕉',
'watermelon' : '西瓜',
};

//我们也可以通过Map对象的构造函数来创建Map对象
var fruit = Map();
fruit['apple'] = '苹果';
fruit['banana'] = '香蕉';
fruit['watermelon'] = '西瓜';
转义符使用

声明raw字符串(前缀为r),在字符串前加字符r,或者在\前面再加一个\
可以避免“\”的转义作用

函数

因为Dart语言是面向对象的语言,所以它的函数也是对象,函数属于Function对象,举个例子:

bool isNumberMoreThanTen(int number) {
return number > 10;
}

可选参数

在写函数的时候,如果我们将函数的参数用**[]**括起来,就可以表明这个参数是可选位置参数,例如

bool isNumberMoreThanOther(int number, [int compareNumber]) {
if (compareNumber != null) {
return number > compareNumber;
}
return number > 10;
}

在这个例子中,number是必须要传如的参数,而compareNumber是可以不传入的参数,这个函数可以做到在compareNumber不传入的时候比较number和10之间的大小关系,在compareNumber传入后比较compareNumber和number之间的大小关系

参数默认值

如果参数指定了默认值,当我们不传入此参数的时候就会用这个默认值,我们可以在上面的例子中稍作改进

bool isNumberMoreThanOther(int number, [int compareNumber = 10]) {
return number > compareNumber;
}

和上面的例子一样,我们实现了同样的效果,但是代码更加简洁了,当我们的compareNumber参数没有被参入的时候,就会使用10这个默认值和number进行大小关系的比较

main函数

所有的Flutter程序都必须要有一个main函数,和C语言一样,这个函数作为程序的入口函数

函数返回值

在Dart语言中,函数的返回值有以下特点:

  • 所有的函数都会有返回值
  • 如果没有指定函数的返回值,默认返回null
  • 没有返回值的函数,系统会在最后添加隐式的return语句

运算符

Dart语言可以支持各种类型的运算符,部分运算符支持重载,完整的支持的操作符表如下:

操作符描述 运算符
一元后缀 expr++、expr–、()、[]、.、?.
一元前缀 -expr、!expr、~expr、++expr、–expr
乘法 *、/、%、~/
加法 +、-
移动位运算 <<、>>
与位运算 &
异或位运算 ^
或位运算 |
关系和类型测试 >=、<=、>、<、as、is、!is
等式 ==、!=
逻辑与 &&
逻辑或 ||
条件 expr ? expr :expr
级联 ..
赋值 =、*=、/=、~/=、%=、+=、-=、<<=、>>=、&=、^=、|=、??=

表中操作符的优先级从上到下逐个减小

类型测试操作符

类型测试操作符主要有以下三个

  • as 类型转换
  • is 当对象是相应类型的时候返回true
  • !is 当对象不是相应类型的时候返回true

赋值操作符

我们可以通过=运算符赋值,如果要在变量为null的时候赋值,可以使用??=运算符赋值

a = value;
b ??= value;

条件表达式

一般我们如果要表达“如果条件为真,返回expr1否则返回expr2”会有如下两种写法

//写法一
if (condition) {
return expr1;
} else {
return expr2;
}
//写法二
condition ? expr1 : expr2;

在Dart语言中还有一种条件表达式,也就是??操作符

expr1 ?? expr2

这种写法表示如果expr1不为null返回其值,否则返回expr2的值

级联操作

级联操作可以对一个对象执行一系列操作,举例:我们创建了一个button对象,我们想要给他设置文本、添加一个样式以及监听事件,一般我们会这样写

button.text = 'TestButton';
button.classes.add(''ButtonOKStyle'');
button.onClick,listen((e) => window.alert('YES'));

用级联操作我们可以将代码简化为:

button
..text = 'TestButton'
..classes.add(''ButtonOKStyle'')
..onClick,listen((e) => window.alert('YES'));

流程控制语言

Dart语言的流程控制语句主要有以下几类:

  • if & else
  • for
  • while & do-while
  • break & continue
  • switch & case
  • assert
  • try-catch & throw

assert

Dart语言通过使用assert语句来中断正常的执行流程,当assert判断的条件为false的时候发生中断并抛出一个AssertionError。assert判断的条件是任何可以转化为boolean类型的对象,即使是函数也可以。例如:

assert(text != null);

面向对象

Dart语言中一个类可以继承自多个父类,也就是多继承,所有的类都有同一个基类Object,这个特性类似于Java。

实例化成员变量

class User {
String name;
int age;
}

main() {
var user = User();
user.name = 'Bob';
user.name = 18;
}

这个是一个简单的实例化成员变量的例子,在Dart的类定义中所有的变量都会隐式的定义setter方法,针对非空变量会额外增加getter方法。

构造函数

常规构造函数

构造函数是用来构造当前类的函数,是一种特殊的函数,函数名称必须要和类名相同

class User {
String name;
int age;

User(String name, int age) {
this.name = name;
this.age = age;
}
}

//代码也可以简化为
class User {
String name;
int age;

User(this.name, this.age);
}
命名的构造函数

使用命名构造函数从另一类或现有的数据中快速实现构造函数。

class User {
String name;
int age;

User(this.name, this.age);

User.formJson(Map join) {
name = json['name'];
age = json['age'];
}
}
构造函数初始化列表

除了调用父类的构造函数,也可以通过初始化列表在子类的构造函数运行前来初始化实例的成员变量值

class User {
final String name;
final int age;

User(name, age)
: name = name,
age = age;
}

main() {
var p = User('TestName', 23);
}

读取和写入对象

get()和set()方法是专门用于读取和写入对象的属性和方法,每一个类的实例,系统都隐式地包含了get()和set()方法

重载操作

举一个比较常见的例子吧,重载+和-操作夫用于向量相加相减

class Vector {
final int x;
final int y;

const Vector(this.x, this.y);

Vector operator +(Vector v) {
return Vector(x + v.x, y + v.y);
}

Vector operator -(Vector v) {
return Vector(x - v.x, y - v.y);
}
}

Mixins

Mixins(混入功能)相当于多继承,通过with关键字来实现

class S {
a() {
print("S.a");
}
}

class A {
a() {
print("A.a");
}
b() {
print("A.b");
}
}

class T = A with S;

main(List<String> args) {
T t = new T();
t.a();
t.b();
}

泛型

泛型通常是为了类型安全而设计的,适当地指定泛型类型会生成更好的代码,Dart语言中使用的方式来定义泛型

var names = List<String>();
names.addAll(['1', '2', '3']);
用于集合类型

泛型用于List和Map类型的参数化

var names = <String>['1', '2', '3'];
var weeks = <String, String> {
'Monday' : '周一',
'Tuesday' : '周二',
'Wednesday' : '周三',
'Thursday' : '周四',
'Friday' : '周五',
'Saturday' : '周六',
'Sunday' : '周日',
};
在构造函数中参数化
var users = Map<String, User>();

异步操作

Dart语言中一般使用async函数和await表达式实现异步操作

Dart库提供了asynchronous功能,该功能通过接口进行耗时操作,并返回Future或者Stream对象

  • 使用async函数和await表达式或者使用Future的API可以返回一个Future对象的值
  • 使用async函数和一个异步循环(await for)或Stream的API可以返回一个Stream对象的值
await readStreamFile()

fileReader () async {
var file = await readStreamFile();
}

必须在一个使用了async关键字标记后的函数中使用await表达式

元数据

使用元数据可以给代码i谭家更多的信息,元数据是以@开始的修饰符,在@后面接着编译时的常量或者调用一个常量的构造函数。目前Dart提供了三个@修饰符

  • @deprecated 被弃用的
  • @override重写
  • @proxy 代理

元数据可以修饰库、类、类型定义、类型参数、构造函数、工厂函数、函数、作用域、参数以及变量声明