一、入口函数

很多程序入口都是从main函数开始,所以dart也不例外,一起来看下百变的main函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//main标准写法
void main() {
print('Hello World!');//注意: Dart和Java一样表达式以分号结尾,写习惯Kotlin的小伙伴需要注意了, 这可能是你从Kotlin转Dart最大不适之一。
}

//dart中void类型,作为函数返回值类型可以省略
main() {
print('Hello World!');
}

//如果函数内部只有一个表达式,可以省略大括号,使用"=>"箭头函数;
//而对于Kotlin则是如果只有一个表达式,可以省略大括号,使用"="连接,类似 fun main(args: Array<String>) = println('Hello World!')
void main() => print('Hello World!');

//最简写形式
main() => print('Hello World!');

二、数据类型

在dart中的一切皆是对象,包括数字、布尔值、函数等,它们和Java一样都继承于Object, 所以它们的默认值也就是null. 在dart主要有: 布尔类型bool、数字类型num(数字类型又分为int,double,并且两者父类都是num)、字符串类型String、集合类型(List, Set, Map)、Runes类和Symbols类型(后两个用的并不太多)

1、布尔类型(bool)

在dart中和C语言一样都是使用bool来声明一个布尔类型变量或常量,但是一致的是它对应的值只有两个true和false.

1
2
3
4
main() {
bool isClosed = true;//注意,dart还是和Java类似的 [类型][变量名]方式声明,这个和Kotlin的 [变量名]:[类型]不一样.
bool isOpened = false;
}

2、数字类型(num、int、double)

在dart中num、int、double都是类,然后int、double都继承num抽象类

![](/Users/mikyou/Library/Application Support/marktext/images/2019-10-24-22-02-40-image.png)

1
2
3
4
5
6
7
main() {
double pi = 3.141592653;
int width = 200;
int height = 300;
print(width / height);//注意:这里和Kotlin、Java都不一样,两个int类型相除是double类型小数,而不是整除后的整数。
print(width ~/ height);//注意: 这才是dart整除正确姿势
}

dart也拥有一些数字常用的函数:

1
2
3
4
5
6
7
8
9
10
11
12
main() {
print(3.141592653.toStringAsFixed(3)); //3.142 保留有效数字
print(6.6.floor());//6向下取整
print((-6.6).ceil()); //-6 向上取整
print(9.9.ceil()); //10 向上取整
print(666.6.round()); //667 四舍五入
print((-666.6).abs()); // 666.6 取绝对值
print(666.6.toInt()); //666 转化成int,这中toInt、toDouble和Kotlin类似
print(999.isEven); //false 是否是偶数
print(999.isOdd); //true 是否是奇数
print(666.6.toString()); //666.6 转化成字符串
}

3、字符串类型(String)

在Dart中支持单引号、双引号、三引号以及$字符串模板用法和Kotlin是一模一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
main() {
String name = 'Hello Dart!';//单引号
String title = "'Hello Dart!'";//双引号
String description = """
Hello Dart! Hello Dart!
Hello Dart!
Hello Dart! Hello Dart!
""";//三引号
num value = 2;
String result = "The result is $value";//单值引用
num width = 200;
num height = 300;
String square = "The square is ${width * height}";//表达式的值引用
}

dart中也有很多字符串操作的方法,比如字符串拆分、子串等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
main() {
String url = "https://mrale.ph/dartvm/";

print(url.split("://")[0]); //字符串分割split方法,类似Java和Kotlin

print(url.substring(3, 9)); //字符串截取substring方法, 类似Java和Kotlin

print(url.codeUnitAt(0)); //取当前索引位置字符的UTF-16码

print(url.startsWith("https")); //当前字符串是否以指定字符开头, 类似Java和Kotlin

print(url.endsWith("/")); //当前字符串是否以指定字符结尾, 类似Java和Kotlin

print(url.toUpperCase()); //大写, 类似Java和Kotlin

print(url.toLowerCase()); //小写, 类似Java和Kotlin

print(url.indexOf("ph")); //获取指定字符的索引位置, 类似Java和Kotlin

print(url.contains("http")); //字符串是否包含指定字符, 类似Java和Kotlin

print(url.trim()); //去除字符串的首尾空格, 类似Java和Kotlin

print(url.length); //获取字符串长度

print(url.replaceFirst("t", "A")); //替换第一次出现t字符位置的字符

print(url.replaceAll("m", "M")); //全部替换, 类似Java和Kotlin
}

4、类型检查(is和is!)和强制类型转换(as)

dart也是通过 is 关键字来对类型进行检查以及使用 as 关键字对类型进行强制转换,如果判断不是某个类型dart中使用 is! 。

1
2
3
4
5
6
7
8
main() {
int number = 100;
double distance = 200.5;
num age = 18;
print(number is num);//true
print(distance is! int);//true
print(age as int);//18
}

5、Runes和Symbols类型

在Dart中的Runes和Symbols类型使用并不多,这里做个简单的介绍, Runes类型是UTF-32字节单元定义的Unicode字符串,Unicode可以使用数字表示字母、数字和符号,然而在dart中String是一系列的UTF-16的字节单元,所以想要表示32位的Unicode的值,就需要用到Runes类型。我们一般使用\uxxxx这种形式来表示一个Unicode码,xxxx 表示4个十六进制值。当十六进制数据多余或者少于4位时,将十六进制数放入到花括号中,例如,微笑表情(😆)是\u{1f600}。而Symbols类型则用得很少,一般用于Dart中的反射,但是注意在Flutter中禁止使用反射。

1
2
3
4
5
6
7
8
9
10
main() {
var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);//返回十六位的字符单元数组
print(clapping.runes.toList());

Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
}

6、Object类型

在Dart中所有东西都是对象,都继承于Object, 所以可以使用Object可以定义任何的变量,而且赋值后,类型也可以更改。

1
2
3
4
main() {
Object color = 'black';
color = 0xff000000;//运行正常,0xff000000类型是int, int也继承于Object
}

7、dynamic类型

在Dart中还有一个和Object类型非常类似的类型那就是dynamic类型,下面讲到的var声明的变量未赋值的时候就是dynamic类型, 它可以像Object一样可以改变类型。dynamic类型一般用于无法确定具体类型, 注意: 建议不要滥用dynamic,一般尽量使用Object, 如果你对Flutter和Native原生通信PlatformChannel代码熟悉的话,你会发现里面大量使用了dynamic, 因为可能native数据类型无法对应dart中的数据类型,此时dart接收一般就会使用dynamic.

Object和dynamic区别在于: Object会在编译阶段检查类型,而dynamic不会在编译阶段检查类型。

1
2
3
4
main() {
dynamic color = 'black';
color = 0xff000000;//运行正常,0xff000000类型是int, int也继承于Object
}

三、变量和常量

1、var关键字

在dart中可以使用var来替代具体类型的声明,会自动推导变量的类型,这是因为var并不是直接存储值,而是存储值的对象引用,所以var可以声明任何变量。注意: 在Flutter开发一般会经常使用var声明变量,以便于可以自动推导变量的类型。

1
2
3
4
5
6
7
8
main() {
int colorValue = 0xff000000;
var colorKey = 'black'; //var声明变量 自动根据赋值的类型,推导为String类型
// 使用var声明集合变量
var colorList = ['red', 'yellow', 'blue', 'green'];
var colorSet = {'red', 'yellow', 'blue', 'green'};
var colorMap = {'white': 0xffffffff, 'black': 0xff000000};
}

但是在使用var声明变量的时候,需要注意的是: 如果var声明的变量开始不初始化,不仅值可以改变它的类型也是可以被修改的,但是一旦开始初始化赋值后,它的类型就确定了,后续不能被改变。

1
2
3
4
5
6
7
8
9
10
11
main() {
var color; // 仅有声明未赋值的时候,这里的color的类型是dynamic,所以它的类型是可以变的
color = 'red';
print(color is String); //true
color = 0xffff0000;
print(color is int); //true

var colorValue = 0xffff0000; //声明时并赋值,这里colorValue类型已经推导出为int,并且确定了类型
colorValue = 'red'; //错误,这里会抛出编译异常,String类型的值不能赋值给int类型
print(colorValue is int); //true
}

2、常量(final和const)

在dart中声明常量可以使用const或final 两个关键字,注意: 这两者的区别在于如果常量是编译期就能初始化的就用const如果常量是运行时期初始化的就用final

1
2
3
4
main() {    
const PI = 3.141592653;//const定义常量
final nowTime = DateTime.now();//final定义常量
}