对于dart的基本认知
JIT 与 AOT
Dart 是少数同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)的语言之一。
AOT 的典型代表是 C/C++,它们必须在执行前编译成机器码;而 JIT 的代表,则包括了如 JavaScript、Python 等几乎所有的脚本语言。
但是dart不支持热更新。
在开发期使用 JIT,开发周期异常短,调试方式颠覆常规(支持有状态的热重载);而发布期使用 AOT,本地代码的执行更高效,代码性能和用户体验也更卓越。
内存分配与垃圾回收
Dart VM 的内存分配策略比较简单,创建对象时只需要在堆上移动指针,内存增长始终是线性的,省去了查找可用内存的过程。
在 Dart 中,并发是通过 Isolate 实现的。Isolate 是类似于线程但不共享内存,独立运行的 worker。这样的机制,就可以让 Dart 实现无锁的快速分配。
Dart 的垃圾回收,则是采用了多生代算法。新生代在回收内存时采用“半空间”机制。
Dart 避免了抢占式调度和共享内存,可以在没有锁的情况下进行对象分配和垃圾回收,在性能方面表现相当不错。
单线程模型
一旦某个函数开始执行,就将执行到这个函数结束,而不会被其他 Dart 代码打断。所以,Dart 中并没有线程,只有 Isolate(隔离区)。Isolates 之间不会共享内存,就像几个运行在不同进程中的 worker,通过事件循环(Event Looper)在事件队列(Event Queue)上传递消息通信。
1.I/O、网络请求操作系统提供了异步的API
2.CPU密集型的操作用Isolate即可
无需单独的声明式布局语言
在 Flutter 中,界面布局直接通过 Dart 编码来定义。
dart语法
Dart 的变量与类型
在 Dart 中,我们可以用 var 或者具体的类型来声明一个变量。当使用 var 定义变量时,表示类型是交由编译器推断决定的。
在默认情况下,未初始化的变量的值都是 null。
Dart 是类型安全的语言,并且所有类型都是对象类型,都继承自顶层类型 Object,因此一切变量的值都是类的实例(即对象),甚至数字、布尔值、函数和 null 也都是继承自 Object 的对象。
常量定义
const,表示变量在编译期间即能确定的值;
final 则不太一样,用它定义的变量可以在运行时确定值,而一旦确定后就不可再变。
函数
函数也是对象,它的类型叫作 Function,可以在函数中传递。
bool isZero(int number) { //判断整数是否为0
return number == 0;
}
void printInfo(int number,Function check) { //用check函数来判断整数是否为0
print("{check(number)}");
}
Function f = isZero;
int x = 10;
int y = 0;
printInfo(x,f); // 输出 10 is Zero: false
printInfo(y,f); // 输出 0 is Zero: true
函数重载
Dart 认为重载会导致混乱,因此从设计之初就不支持重载,而是提供了可选命名参数和可选参数。具体方式是,在声明函数时:给参数增加{},以 paramName: value 的方式指定调用参数,也就是可选命名参数;给参数增加[],则意味着这些参数是可以忽略的,也就是可选参数。
tips:可选命名参数是指在调用时需要带上参数名称,如enable1Flags(bold: true, hidden: false);,而可选参数则不用,如enable3Flags(true, false)
//要达到可选命名参数的用法,那就在定义函数的时候给参数加上 {}
void enable1Flags({bool bold, bool hidden}) => print("$bold , $hidden");
//定义可选命名参数时增加默认值
void enable2Flags({bool bold = true, bool hidden = false}) => print("$bold ,$hidden");
//可忽略的参数在函数定义时用[]符号指定
void enable3Flags(bool bold, [bool hidden]) => print("$bold ,$hidden");
//定义可忽略参数时增加默认值
void enable4Flags(bool bold, [bool hidden = false]) => print("$bold ,$hidden");
//可选命名参数函数调用
enable1Flags(bold: true, hidden: false); //true, false
enable1Flags(bold: true); //true, null
enable2Flags(bold: false); //false, false
//可忽略参数函数调用
enable3Flags(true, false); //true, false
enable3Flags(true,); //true, null
enable4Flags(true); //true, false
enable4Flags(true,true); // true, true
public、protected、private关键字
Dart 中并没有 public、protected、private 这些关键字,我们只要在声明变量与方法时,在前面加上“”即可作为 private 方法使用。如果不加“”,则默认为 public。不过,“_”的限制范围并不是类访问级别的,而是库访问级别。
继承与复用
在 Dart 中,你可以对同一个父类进行继承或接口实现:
- 继承父类意味着,子类由父类派生,会自动获取父类的成员变量和方法实现,子类可以根据需要覆写构造函数及父类方法;
- 接口实现则意味着,子类获取到的仅仅是接口的成员变量符号和方法符号,需要重新实现成员变量,以及方法的声明和初始化,否则编译器会报错。
tips:dart中可以implements一个类。
class Point {
num x = 0, y = 0;
void printInfo() => print('($x,$y)');
}
//Vector继承自Point
class Vector extends Point{
num z = 0;
@override
void printInfo() => print('($x,$y,$z)'); //覆写了printInfo实现
}
//Coordinate是对Point的接口实现
class Coordinate implements Point {
num x = 0, y = 0; //成员变量需要重新声明
void printInfo() => print('($x,$y)'); //成员函数需要重新声明实现
}
var xxx = Vector();
xxx
..x = 1
..y = 2
..z = 3; //级联运算符,等同于xxx.x=1; xxx.y=2;xxx.z=3;
xxx.printInfo(); //输出(1,2,3)
var yyy = Coordinate();
yyy
..x = 1
..y = 2; //级联运算符,等同于yyy.x=1; yyy.y=2;
yyy.printInfo(); //输出(1,2)
print (yyy is Point); //true
print(yyy is Coordinate); //true
除了继承和接口实现之外,Dart 还提供了另一种机制来实现类的复用,即“混入”(Mixin)。
tips:混入with本质上是多继承, 当被混入的类有多个同名方法时,调用子类的该方法时,会调用with声明的最后一个拥有该方法的类中的该方法,同时混入中的父类不能继承
class Point { num x = 0, y = 0; void printInfo() => print('($x,$y)');}
class Coordinate with Point {
}
var yyy = Coordinate();
print (yyy is Point); //true
print(yyy is Coordinate); //true
运算符
- ?. 运算符:假设 Point 类有 printInfo() 方法,p 是 Point 的一个可能为 null 的实例。那么,p 调用成员方法的安全代码,可以简化为 p?.printInfo() ,表示 p 为 null 的时候跳过,避免抛出异常。
- ??= 运算符:如果 a 为 null,则给 a 赋值 value,否则跳过。这种用默认值兜底的赋值语句在 Dart 中我们可以用 a ??= value 表示。
- ?? 运算符:如果 a 不为 null,返回 a 的值,否则返回 b。在 Java 或者 C++ 中,我们需要通过三元表达式 (a != null)? a : b 来实现这种情况。而在 Dart 中,这类代码可以简化为 a ?? b。
- ..级联运算符,在同一个对象上连续调用多个函数以及访问成员变量
void main() {
ShoppingCart.withCode(name:'张三', code:'123456')
..bookings = [Item('苹果',10.0), Item('鸭梨',20.0)]
..printInfo();
ShoppingCart(name:'李四')
..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
..printInfo();
}
运算符重载
class Vector {
num x, y;
Vector(this.x, this.y);
// 自定义相加运算符,实现向量相加
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
// 覆写相等运算符,判断向量相等
bool operator == (dynamic v) => x == v.x && y == v.y;
}
final x = Vector(3, 3);
final y = Vector(2, 2);
final z = Vector(1, 1);
print(x == (y + z)); // 输出true
网友评论