2019-03-19 _Dart 2.2.1
首先Dart网站的重要的概念应该看一下:
在学习 Dart 的时候,请牢记下面一些事实和概念:
- 所有能够使用变量引用的都是对象, 每个对象都是一个类的实例。在 Dart 中 甚至连 数字、方法和
null
都是对象。所有的对象都继承于 Object 类。 - 使用静态类型(例如前面示例中的
num
) 可以更清晰的表明你的意图,并且可以让静态分析工具来分析你的代码, 但这并不是牵制性的。(在调试代码的时候你可能注意到 没有指定类型的变量的类型为dynamic
。) - Dart 在运行之前会先解析你的代码。你可以通过使用 类型或者编译时常量来帮助 Dart 去捕获异常以及 让代码运行的更高效。
- Dart 支持顶级方法 (例如
main()
),同时还支持在类中定义函数。 (静态函数和实例函数)。 你还可以在方法中定义方法 (嵌套方法或者局部方法)。 - 同样,Dart 还支持顶级变量,以及 在类中定义变量(静态变量和实例变量)。 实例变量有时候被称之为域(Fields)或者属性(Properties)。
- 和 Java 不同的是,Dart 没有
public
、protected
、 和private
关键字。如果一个标识符以 (_) 开头,则该标识符 在库内是私有的。详情请参考: 库和可见性。 - 标识符可以以字母或者 _ 下划线开头,后面可以是 其他字符和数字的组合。
- 有时候 表达式 expression 和 语句 statement 是有区别的,所以这种情况我们会分别指明每种情况。
- Dart 工具可以指出两种问题:警告和错误。 警告只是说你的代码可能有问题, 但是并不会阻止你的代码执行。 错误可以是编译时错误也可以是运行时错误。遇到编译时错误时,代码将 无法执行;运行时错误将会在运行代码的时候导致一个 异常。
变量
- 可以使用 var 声明变量( java 10也可以 )
var a = 10;
- 另外对于动态类型 Dart 还有
dynamic
关键字 - Dart 所有变量如果未初始化都为
null
,不像 javaint
的默认值是 0,boolean
的默认值是 false -
final
表示不可变,const
表示常量,static
表示的意义相同都是可以直接通过类名的方式使用方法和属性
内建类型
- 没有
float
类型,int
和double
都是num
的子类 -
String
字符串内部可以使用表达式${}
,(和kotlin
的使用方式一致),使用单引号和双引号包围,使用三个单引号或双引号包围的字符可以换行,支持emoji表情
var s = 'string interpolation';
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s4 = "That deserves all caps. ${s.toUpperCase()} is very handy!";
var s5 = '''
You can create
multi-line strings like this one.
''';
var s6 = """This is also a
multi-line string.""";
var clapping = '\u{1f44f}'; //
- 没有数组只有列表,List, Set, Map 不是抽象接口,可以直接使用,并且支持泛形
var list = [1, 2, 3]; // 列表
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; // Set
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
}; // Map
方法
- 支持顶级方法,方法也是对象, 支持
lambda
表达式的写法 - 如果方法的参数是解构出来的可以通过
@required
注解标注为必填const Scrollbar({Key key, @required Widget child})
- 支持可选参数,可选参数写在最后并且使用
[]
包围String say(String from, String msg, [String device])
- 支持默认参数
void enableFlags({bool bold = false, bool hidden = false}) {...}
- 支持匿名方法
(参数){方法体}
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
- 支持闭包
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
操作符
-
as , is, is!
:as
类似与强制类型转换,is
类似instanceof
- 空替换
??
:String playerName(String name) => name ?? 'Guest';
等价于String playerName(String name) => name != null ? name : 'Guest';
- 级联符号 (..) 可以代替构建者模式
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
// 使用级联操作
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
-
?.
操作符当对象不为空时调用后面的属性或方法:foo?.a
类似于if( foo != null) f.a;
异常
- Dart的异常是不用必须捕获的
-
try {} catch
有点不一样
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 只捕获 OutOfLlamasException
buyMoreLlamas();
} on Exception catch (e) {
// 上面不能捕获的且是Exception的子类
print('Unknown exception: $e');
} catch (e,s) {
// 其余的所有异常,s ==》 stack trace
print('Something really unknown: $e');
rethrow; //不处理,直接抛出去
}
类
- 创建对象可以不使用
new
关键字 - 可以给构造方法命名
class Point {
num x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
- 调用父类的构造方法(
:
)
class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
- 在构造方法的方法体调用之前初始化属性
import 'dart:math';
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(x, y)
: x = x,
y = y,
distanceFromOrigin = sqrt(x * x + y * y);
}
- 常量构造方法,在构造方法之前使用
const
修饰,属性必需是final
或者const
的
class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
final num x, y;
const ImmutablePoint(this.x, this.y);
}
const ca = ImmutablePoint(1,1); // const 修饰的变量 必须是const的构造方法
var a = const ImmutablePoint(1, 1);
var b = const ImmutablePoint(1, 1);
assert(identical(a, b)); // true
-
factory
修饰的构造方法为工厂方法
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to
// the _ in front of its name.
static final Map _cache =
{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
-
runtimeType
关键字 获取变量运行时的类型print('The type of a is ${a.runtimeType}');
Dart 的泛形是不擦除的 -
getter
和setter
: 通过这两个关键字可以自定义属性的值
class Rectangle {
num left, top, width, height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and 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;
}
- 没有
interfaces
关键字,每个类都是一个接口 -
支持操作符重载
- 支持重写
noSuchMethod()
方法,当对象调用不存在的属性或方法时该方法会被调用 - 支持混入
mixin
, 提供by, mixin, mixin ..on
关键字
泛形
- Java 运行时会擦除泛形,Dart 不会
var names = List();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List); // true
库和可见性
- Dart 使用 URI 来确定一个库, 可以给库添加前缀(使用
as
关键词)
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
- 支持导入部分库(
show
),或者隐藏部分库(hide
)
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
- 支持懒加载
deferred as
import 'package:greetings/hello.dart' deferred as hello;
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
异步
-
async, await
关键字, 声明耗时操作,返回值必须是Future
方法名后用async
标注, 调用耗时操作时需要使用await
关键字,并且在async
标注的方法中
Future lookUpVersion() async => '1.0.0';
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
-
Stream
关键字使用await for
或者listen
方法
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
生成器
- 方法体使用
sync*
标注, 返回值前添加yeild
, 返回值 Iterable 表示同步, Stream 表示异步, 如果返回值为递归使用yeild *
来提高性能
// 同步
Iterable naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
// 异步
Stream asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
// 返回值为递归
Iterable naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
可运行的类
- 如果类中实现了
call
方法, 那么这个类就是可执行的
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');
}
Typedefs
- 使用
typedef
关键字 标注方法签名,可以避免方法签名的丢失
typedef Compare = int Function(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
注解
- Dart 使用类来声明注解, Java 使用
@interface
; 另外 Dart 貌似没有地方声明注解的使用范围
注释
- Dart 可以使用
///, /**
编写文档注释