Dart学习笔记
快速过一下Dart的基本语法特性,感兴趣的都记录下,后面详细整理
一 变量
- 代码中的硬编码值称之为字面量
- Dart中所有类型都是对象,包括函数、字符、null都是对象。
- var 用于声明创建变量,显式声明或者根据赋值自动推断变量类型,dynamic 标记变量为可变类型,可接受多种类型数据。
var name = 'Bob';
dynamic name = 'Bob';
String name = 'Bob';
- 所有默认值都是null,可以使用assert判断类型,assert在生产环境会被忽略。assert 的第一个参数可以是解析为布尔值的任何表达式。 如果表达式结果为 true , 则断言成功,并继续执行。 如果表达式结果为 false , 则断言失败,并抛出异常 (AssertionError) 。
int lineCount;
assert(lineCount == null);
- final标记为运行时常量,只能被赋值一次。const 定义编译时常量,编译时就已经确定值。
final String nickname = 'Bobby';
const baz = [];
-
Number 包含64位int和double
-
String 是一组UTF-16单元序列,可以做在字符串中使用${lineCount} 运行内嵌变量或者内嵌表达式,内嵌变量的时候可以不需要括号。==就是判断字符串序列是否相等。使用r前缀可以创建原始raw字符串。
var s = r"In a raw string, even \n isn't special."; -
dart中的数组就是list,
var foo = [1,2,3,4,5]; print(foo.length); -
Set类型是一个元素唯一切无序的集合
-
Rune是用来表示字符串中的UTF-32编码字符的
二 函数
-
=> *expr*语法是{ return *expr*; }的简写。=>符号 有时也被称为 箭头 语法。 -
命名可选参数 ,使用 {param1, param2, …} 来指定命名参数:
void enableFlags({bool bold, bool hidden}) {...} -
位置可选参数, 将参数放到
[]中来标记参数是可选的: 即调用时非必须的参数。String say(String from, String msg, [String device]) -
默认参数值,使用=为参数创建默认值
void enableFlags({bool bold = false, bool hidden = false}) {...} -
main()函数,任何应用都必须包含一个main()函数作为入口,main()返回值为空,参数为一个可选的List
void main() { querySelector('#sample_text_id') ..text = 'Click me!' ..onClick.listen(reverseText); } // 这样运行应用: dart args.dart 1 test void main(List<String> arguments) { print(arguments); } -
级联操作符… 使用级联调用可以连续调用一个对象上的多个方法。
querySelector('#sample_text_id') ..text = 'Click me!' ..onClick.listen(reverseText); -
Dart中的函数是一等对象,可以作为其他方法的参数,也可以将一个函数赋值给一个变量。
void printElement(int element) { print(element); } var list = [1, 2, 3]; // 将 printElement 函数作为参数传递。 list.forEach(printElement); var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!'; -
匿名函数或者闭包使用如下方式定义,参数列表和花括号包围的代码主体。
([[Type] param1[, …]]) {
codeBlock;
}; -
变量作用于是变量定义的花括号范围之内。
-
闭包比较特殊,它是一个函数对象,即使闭包定义在
-
所有的函数都有返回值,即使没有指定返回值,都会隐式添加return null;
三 运算符
-
除法运算符有个新加的语法,整除除法
assert(5 / 2 == 2.5); // 结果是双浮点型 assert(5 ~/ 2 == 2); // 结果是整型 -
大多数情况下判断两个对象是否相等,都可以使用==运算符,极少数情况也可以使用identical()。
-
as 可以将对象强转为特定类型,
(emp as Person).firstName = 'Bob'; -
is 判断对象是否是特定类型,is! 判断对象不是特定类型
if (emp is Person) { -
使用=赋值一定会为变量赋值,使用??=运算符只有前面变量为null才会赋值。
// 将值赋值给变量a a = value; // 如果b为空时,将变量赋值给b,否则,b的值保持不变。 b ??= value; -
条件运算符 expr1 ?? expr2 当前置变量expr1 为非空,则返回expr1,否则返回expr2。
-
级联运算符,可以连续调用一个对象上的方法,也可以访问一个对象上的变量。其实看着有点懵逼
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();
四 控制流
控制流基本上和java一样,在对象实现Iterable接口的情况下,下面的调用很有意思
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
五 异常
Dart的异常分为Exception和Error,但也可以抛出其他非空类型的对象。
throw FormatException('Expected at least 1 section');
throw 'Out of llamas!';
异常捕获可以使用try on 或者catch,on 匹配指定类型错误,但不会传递错误对象。catch可以捕捉指定类型或者其他所有异常。
如果捕捉的异常还想扔出来,可以使用rethrow
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 一个特殊的异常
buyMoreLlamas();
} on Exception catch (e) {
// 其他任何异常
print('Unknown exception: $e');
} catch (e) {
// 没有指定的类型,处理所有异常
print('Something really unknown: $e');
}
finally 不管是否抛出异常,定义了一定会执行到这里。
六 类
-
dart类的继承使用的是Mixin 混入的意思,
使用多继承会有结构复杂,继承路径模糊,方法冲突等问题,为了解决这些问题,有规格继承和实现继承两种方式,规格继承就是只多继承方法声明集合,而实现继承不仅包含方法声明还包含方法实现继承。java使用规格继承就是interface,
继承强调I am,Mixin强调的是I can
-
调用方法和属性时可以使用
?.语法,可以避免对象为空造成的异常。// 如果 p 为 non-null,设置它变量 y 的值为 4。 p?.y = 4;
var p1 = Point(2, 2);
var p1 = new Point(2, 2);
- 当类构造函数添加了const时,在使用时也需要添加const 以此创建编译时常量。
- 调用对象的runtimeType属性可以得到对象类型。
- 未初始化的成员变量初始值都为null。
- Dart支持直接通过构造函数定义给成员变量赋值
class Point {
num x, y;
// 在构造函数体执行前,
// 语法糖已经设置了变量 x 和 y。
Point(this.x, this.y);
}
- 默认情况下子类会自动调用父类的无参构造函数,但是如果父类没有无参构造函数,就得在定义子类构造函数时,手动指定调用哪个父类构造函数,
class Employee extends Person {
Employee() : super.fromJson(getDefaultData());
// ···
}
-
工厂构造函数,当一个构造函数并不是每次都重新创建一个新的对象实例时,可以使用factory关键字,标记该构造方法。
-
dart类成员变量都搭配了隐式的get和set方法,方法名同变量名,当然我们可以自己实现。
class Rectangle { num left, top, width, height; Rectangle(this.left, this.top, this.width, this.height); // 定义两个计算属性: right 和 bottom。 num get right => left + width; set right(num value) => left = value - width; num get bottom => top + height; set bottom(num value) => top = value - height; } -
抽象类定义只需要类定义时添加abstract关键字,抽象方法只需要不写实现即可。
-
dart中类也可以作为隐式接口,作为接口时保留了成员变量和成员方法 的定义,可以让其他类实现该接口。
// person 类。 隐式接口里面包含了 greet() 方法声明。
class Person {
// 包含在接口里,但只在当前库中可见。
final _name;
// 不包含在接口里,因为这是一个构造函数。
Person(this._name);
// 包含在接口里。
String greet(String who) => 'Hello, $who. I am $_name.';
}
// person 接口的实现。
class Impostor implements Person {
get _name => '';
String greet(String who) => 'Hi $who. Do you know who I am?';
}
String greetBob(Person person) => person.greet('Bob');
void main() {
print(greetBob(Person('Kathy')));
print(greetBob(Impostor()));
}
- dart中的很多运算符都是可以重载的,为其添加自己的逻辑,需要在类定义的时候添加。
class Vector {
final int x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
// 运算符 == 和 hashCode 部分没有列出。 有关详情,请参考下面的注释。
// ···
}
- 枚举定义
enum Color { red, green, blue }。 - 可以使用 with关键字使用混入
class Musician extends Performer with Musical {
// ···
}
- 静态方法和类变量直接使用static关键字修饰即可。
- 泛型定义和java基本一样,但实现上Dart的泛型是固化的,而Java的泛型信息是被擦除的。
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};
七 库
- 为代码添加依赖,依赖库可以设置别名。
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
- 可以使用show 和 hide来有选择的导入包的一部分。
- 通过使用deffered as XXX 可以指定延迟加载某个库。
八 异步
-
Dart的异步支持中有两个重要的关键字,async 和 await 。async用在方法定义上,标记这个函数为异步函数,异步函数返回的是个Future类型,即便没有返回类型,也会返回Future
Future checkVersion() async { var version = await lookUpVersion(); // Do something with version } -
await 用在一个表达式之前,会阻塞代码执行,直到表达式返回一个Future。
-
生成器,同步生成器返回一个Iterable对象,异步生成器返回一个Stream对象,下面看如何定义生成器
Iterable<int> naturalsTo(int n) sync* { int k = 0; while (k < n) yield k++; }使用 sync* 关键字定义一个同步生成器,有yield生成并对外提供元素。如果是递归生成器,可以使用yield* 返回递归函数调用的生成结果。
Stream<int> asynchronousNaturalsTo(int n) async* { int k = 0; while (k < n) yield k++; }使用 async* 创建异步生成器,同样使用yield生成元素。
649

被折叠的 条评论
为什么被折叠?



