语言特性
- 所有的东西都是对象,所有的对象都是类的实例。即使 数字、函数、null也都是对象。所有的对象都继承自 Object 类。
- 指定静态类型表明你的意图,并使检查类型检查成为可能。在 Dart 1.x 指定类型是可选的,然而 Dart 正在朝着完全类型安全的语言发展。
- 在 Dart 1.x 中,强类型 strong mode 是可选的,但在 Dart 2 中,默认就是 strong mode。
- Dart 在运行前解析所有的代码,可以使用些小技巧,例如:通过使用类型或编译时常量,来捕捉错误或使代码运行的更快。
- Dart 支持顶级的函数,也支持类或对象的静态和实例方法。也可以在函数内部嵌套函数或本地函数。同样,Dart 支持顶级的变量,也支持类或对象的静态变量和实例变量(也被称作字段或属性)。
- Dart没有 public、protected、private 等关键字,如果一个标识符以 _开头则表示私有。
- 标识符以小写字母或下划线_开头,后面跟着字符和数字的任意组合。
- 明确区分表达式和语句。
- Dart tools 会报告两种类型的问题:警告(warnings)和错误(errors)。警告仅标志着你的代码可能不会工作,但并不会阻止程序执行;错误可能是编译时错误,也可能是运行时错误。编译时错误会阻止程序执行;运行时错误会在程序执行时抛出异常。
- Dart 1.x 有两种运行时模式:生产模式和检查模式。推荐在开发和 debug 时使用检查模式,部署到生产模式。生产模式时 Dart 程序默认的运行时模式。
- Dart 2 废弃了 checked mode 默认 strong mode。
- Dart 2 不再使用 Dartium,改为 dartdevc(DDC)。
- 没有初始化的变量都会被赋予默认值 null。
- final的值只能被设定一次。const 是一个编译时的常量,可以通过 const 来创建常量值,var c=const[];,这里 c 还是一个变量,只是被赋值了一个常量值,它还是可以赋其它值。实例变量可以是 final,但不能是 const。
关键字
关键字 | - | - | - |
---|---|---|---|
abstract | do | import | super |
as | dynamic | in | |
assert | else | interface | sync* |
enum | implements | is | this |
async* | export | library | throw |
await | external | mixin | true |
break | extends | new | try |
case | factory | null | typedef |
catch | false | operator | var |
class | final | part | void |
const | finally | rethrow | while |
continue | for | return | with |
covariant | get | set | yield* |
default | if | static | deferred |
变量
dart会做类型推断。
The type of the name variable is inferred to be String, but you can change that type by specifying it. If an object isn’t restricted to a single type, specify the Object or dynamic type,
var name = 'Bob';
dynamic name = 'Bob';
2
String name = 'Bob';
缺省值
Uninitialized variables have an initial value of null. Even variables with numeric types are initially null, because numbers—like everything else in Dart—are objects.
int lineCount;
assert(lineCount == null);
2
Note: The assert() call is ignored in production code. During development, assert(condition) throws an exception unless condition is true. For details, see Assert.
Final and const
- 如果定义的变量的值不会发生变化,可以使用final或者const声明
- final 只能被设置一次
- const是编译时常量
see:https://news.dartlang.org/2012/06/const-static-final-oh-my.html
数据类型
Numbers
- int Integer values no larger than 64 bits, depending on the platform. On the Dart VM, values can be from -263 to 263 - 1. Dart that’s compiled to JavaScript uses JavaScript numbers, allowing values from -253 to 253 - 1.
- double 64-bit (double-precision) floating-point numbers, as specified by the IEEE 754 standard.
Strings
Booleans
Lists
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
2
3
4
5
6
Maps
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
var gifts = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Runes
In Dart, runes are the UTF-32 code points of a string.
Symbols
A Symbol object represents an operator or identifier declared in a Dart program. You might never need to use symbols, but they’re invaluable for APIs that refer to identifiers by name, because minification changes identifier names but not identifier symbols.
To get the symbol for an identifier, use a symbol literal, which is just # followed by the identifier:
#radix
#bar
2
Symbol literals are compile-time constants.
函数
Dart是面向对形象的语言,即时是函数也有类型,函数属于Function对象。
For functions that contain just one expression, you can use a shorthand syntax:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
The =>
expr syntax is a shorthand for { return expr; }.
The => notation is sometimes referred to as arrow syntax.
Note: Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (😉. For example, you can’t put an if statement there, but you can use a conditional expression.
函数可以有2中类型参数,必须的和可选的。
必须参数
You can annotate a named parameter in any Dart code (not just Flutter) with @required to indicate that it is a required parameter. For example:
const Scrollbar({Key key, Widget child})
Required is defined in the meta package. Either import package:meta/meta.dart directly, or import another package that exports meta, such as Flutter’s package:flutter/material.dart.
可选参数
可选的命名参数
定义命名函数 When defining a function, use {param1, param2, …} to specify named parameters:
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}
2
调用函数
enableFlags(bold: true, hidden: false);
可选位置参数
Wrapping a set of function parameters in [] marks them as optional positional parameters:
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
2
3
4
5
6
7
8
9
10
11
12
缺省参数值
/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}
// bold will be true; hidden will be false.
enableFlags(bold: true);
2
3
4
5
设定缺省位置参数值
String say(String from, String msg,
[String device = 'carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
assert(say('Bob', 'Howdy') ==
'Bob says Howdy with a carrier pigeon');
2
3
4
5
6
7
8
9
10
11
12
13
14
The main() function
Every app must have a top-level main() function, which serves as the entrypoint to the app. The main() function returns void and has an optional List<String>
parameter for arguments.
函数作为参数传递
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// Pass printElement as a parameter.
list.forEach(printElement);
2
3
4
5
6
7
8
函数赋值给一个变量
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');
2
匿名函数
([[Type] param1[, …]]) {
codeBlock;
};
2
3
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
2
3
4
变量作用域
Dart is a lexically scoped language, which means that the scope of variables is determined statically, simply by the layout of the code. You can “follow the curly braces outwards” to see if a variable is in scope.
Here is an example of nested functions with variables at each scope level:
bool topLevel = true;
void main() {
var insideMain = true;
void myFunction() {
var insideFunction = true;
void nestedFunction() {
var insideNestedFunction = true;
assert(topLevel);
assert(insideMain);
assert(insideFunction);
assert(insideNestedFunction);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
变量闭包?
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);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
函数返回值
All functions return a value. If no return value is specified, the statement return null; is implicitly appended to the function body.
foo() {}
assert(foo() == null);
2
3
运算符
条件表达式
Dart has two operators that let you concisely evaluate expressions that might otherwise require if-else statements:
condition ? expr1 : expr2 If condition is true, evaluates expr1 (and returns its value); otherwise, evaluates and returns the value of expr2. expr1 ?? expr2 If expr1 is non-null, returns its value; otherwise, evaluates and returns the value of expr2.
When you need to assign a value based on a boolean expression, consider using ?:.
var visibility = isPublic ? 'public' : 'private';
If the boolean expression tests for null, consider using ??.
String playerName(String name) => name ?? 'Guest';
2
级联符号 (..)
Cascades (..) allow you to make a sequence of operations on the same object. In addition to function calls, you can also access fields on that same object. This often saves you the step of creating a temporary variable and allows you to write more fluid code.
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
2
3
4
等同于
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
2
3
4
Note: Strictly speaking, the “double dot” notation for cascades is not an operator. It’s just part of the Dart syntax.
控制语句
控制语句上与其他语言都差不多
- if and else
- for loops
- while and do-while loops
- break and continue
- switch and case
- assert
异常
类
Getting an object’s type
print('The type of a is ${a.runtimeType}');
Getters and setters
You can create additional properties by implementing getters and setters, using the get and set keywords:
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;
}
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
泛型
库与可见性
异步支持
Dart libraries are full of functions that return Future or Stream objects. These functions are asynchronous: they return after setting up a possibly time-consuming operation (such as I/O), without waiting for that operation to complete.
The async and await keywords support asynchronous programming, letting you write asynchronous code that looks similar to synchronous code.
Handling Futures
When you need the result of a completed Future, you have two options:
Use async and await. Use the Future API, as described in the library tour.
await lookUpVersion();
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
2
3
4
5
6
Handling Streams
When you need to get values from a Stream, you have two options:
- Use async and an asynchronous for loop (await for).
- Use the Stream API, as described in the library tour.
发生器
When you need to lazily produce a sequence of values, consider using a generator function. Dart has built-in support for two kinds of generator functions:
- Synchronous generator: Returns an Iterable object.
- Asynchronous generator: Returns a Stream object.
To implement a synchronous generator function, mark the function body as sync*, and use yield statements to deliver values:
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
2
3
4
To implement an asynchronous generator function, mark the function body as async*, and use yield statements to deliver values:
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
2
3
4
If your generator is recursive, you can improve its performance by using yield*:
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
2
3
4
5
6
Callable classes
To allow your Dart class to be called like a function, implement the call() method.
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');
}
2
3
4
5
6
7
8
9
10
Isolates
Typedef
class SortedCollection {
Function compare;
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
// All we know is that compare is a function,
// but what type of function?
assert(coll.compare is Function);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
}
``
## Metadata
Two annotations are available to all Dart code: @deprecated and @override. For examples of using @override, see Extending a class. Here’s an example of using the @deprecated annotation:
## Comments
### Single-line comments
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
void main() { // TODO: refactor into an AbstractLlamaGreetingFactory? print('Welcome to my Llama farm!'); }
### Multi-line comments
2
void main() { /*
- This is a lot of work. Consider raising chickens.
Llama larry = Llama(); larry.feed(); larry.exercise(); larry.clean(); */ }
### Documentation comments
/// A domesticated South American camelid (Lama glama). /// /// Andean cultures have used llamas as meat and pack /// animals since pre-Hispanic times. class Llama { String name;
/// Feeds your llama [Food]. /// /// The typical llama eats one bale of hay per week. void feed(Food food) { // ... }
/// Exercises your llama with an [activity] for /// [timeLimit] minutes. void exercise(Activity activity, int timeLimit) { // ... } }
2