2019-03-19 _Dart 2.2.1
首先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 ,不像 java int 的默认值是 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, 返回值 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 可以使用 ///, /** 编写文档注释