基本数据类型
Number
-
int
- int a = 1;
- int b = 0xDEFFFF;
-
double
- double x = 1.0;
-
转换
- var a = int.parse('1');
- var b = double.parse('2.5');
- 指定进制:
var hex = int.parse('10', radix: 16); - String a = 1.toString();
- String b = 3.1415.toStringFixed(2);
b = '3.14'
String
- var a = 'this is a string text';
- var b = '''
this is a multiple line string
text....
''';
Boolean
- bool a = true;
- bool b = 1 > 0;
List
- var a = [1, 2, 3];
- List<String> = ['a', 'b'];
- [1,2,3].sort((a,b) => a.compareTo(b));
Set
- var a = {'a', 'b'};
- .length
- .add()
- .addAll(aSet)
Map
- var aMap = Map();
- var aMap = {};
- Map<String, dynamic> map = {
'a': 1,
'b': 'hello',
'c': ()=>print('hello')
};
map.forEach((key, val){
print('val');
}); - Map<int, String> b = {0: 'a', 1: 'b'};
Rune
- UTF-32编码字符
- (♥) 是 \u2665
- (�) 是 \u{1f600} -- 非4个字符的用{}包裹
函数
Function类
- int aFunc(int a, int b) => a+b;
- void aFunc(){}
- aFunc(){}
- 用{}指定命名参数
aFunc(title: String, {Key key, @required Widget child}) - 用[]指定可选参数
aFunc(title: String, {Key key, @required Widget child}) - 设置默认参数值
aFunc(title: 'hello', {Key key, @required Widget child}) - 匿名函数(lambda/closure):(){}
- 函数返回类型
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}
运算符
算数
- ~/
除数取整:5 ~/ 2 = 2 - %
除数取余:5 % 2 = 1
类型判定
- as:将对象强制转换为特定类型
(emp as Person).firstName = 'Bob'; - is:判定对象是否是指定的类型
obj is Object;
is!:是上面的取反
赋值运算符
- ??=
b ??= 'a'; (如果b为null,则b='a',否则不变)
条件表达式
- ? :
a = b>0 ? 'yes' : 'no'; - ??
a = b ?? 'a'; (如果b为null,则a='a',否则a=b)
级联运算符
- .. :对同一个对像进行一系列的操作
querySelector('#confirm') // 获取对象。
..text = 'Confirm' // 调用成员变量。
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
上面代码等同于:
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
- 严格的来讲, “两个点” 的级联语法不是一个运算符。 它只是一个 Dart 的特殊语法。
可选类型(类似swift的Optional)
- ?.
a = obj?.name; (如果obj为null,则a=null;
如果obj.name为null,a=null)
控制流程语句
if-else
for
for(var i=0; i<5; i++){}
-
forEach
- [1,2,3].forEach((val) => print('val: $val'));
-
for-in
- (for var i in [1,2,3]){}
switch-case
- var word = 'a';
switch(word){
case 'b':
print('hello b');
break;
default: break;
}
assert
- assert(text != null);
- assert 语句只在开发环境中有效, 在生产环境是无效的;
枚举
enum Color {
red, green, blue
}
Color.red.index == 0;
Color.values[0] == Color.red;
异常
try-catch
- try{
doingSomething();
} on Exception catch(e) {
print('明确类型的异常');
} catch(e, s){
print('不明确的异常:s');
}
rethrow
finally
- try{
} finally {
} - try{
} catch(e) {
} finally {
}
类
Dart 是一种基于类和 mixin 继承机制的面向对象的语言。
继承用extends关键字;
实现多个接口(抽象类)用implements关键字;
重写父类方法用@override关键字;
获取对象的类型
- Type aType = a.runtimeType;
实例变量
- class Point {
int x; // 声明实例变量 x,初始值为 null 。
int y; // 声明实例变量 y,初始值为 null 。
double z = 0; // 声明示例变量 z,初始值为 0 。
} - 所有未初始化的实例变量默认值都为 “null” ,而不是int的为0
- 隐式生成setter和getter方法
构造函数
-
默认构造函数
- var p = Person();
var p = new Person(); (new是可选的)
- var p = Person();
-
自定义构造函数
- Person(int age, String name){
this.age = age;
this.name = name;
}
this指代当前实例对象,跟oc中的self一样。
上面的代码等同于:
Person(this.age, this.name);
- Person(int age, String name){
- 子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数)。
- 如果希望使用父类中定义的命名构造函数创建子类, 就必须在子类中实现该构造函数。
- 默认情况下,子类的构造函数会自动调用父类的默认构造函数
-
命名构造函数
- 指定意图的构造函数:
Point.origin() {
x = 0;
y = 0;
}
- 指定意图的构造函数:
-
父类构造函数
- class Person {
String firstName;
Person.fromJson(Map data) {
print('in Person');
}
} - class 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');
}
}
main() {
var emp = new Employee.fromJson({});
// Prints:
// in Person
// in Employee
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}
(emp as Person).firstName = 'Bob';
}
- // 在构造函数体执行之前,
// 通过初始列表设置实例变量。
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): (y)');
}
-
工厂构造函数
- 一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。
- class Logger {
final String name;
bool mute = false;
// 从命名的 _ 可以知,
// _cache 是私有属性。
static final Map<String, Logger> _cache =
<String, Logger>{};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);
}
} -
getters & setter
- 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;
} - class Rectangle {
void main() {
var rect = Rectangle(3, 4, 20, 15);
assert(rect.left == 3);
rect.right = 12;
assert(rect.left == -8);
}
-
抽象类
- 抽象方法只存在于 抽象类 中。
- abstract class Doer {
// 定义实例变量和方法 ...
void doSomething(); // 定义一个抽象方法。
}
class EffectiveDoer extends Doer {
void doSomething() {
// 提供方法实现,所以这里的方法就不是抽象方法了...
}
}
-
noSuchMethod()
- 这样可以避免一些dynamic类型的实例对象类型错误,导致访问某些方法时崩溃问题;
如Person a = null; a.name(崩溃); - class A {
// 如果不重写 noSuchMethod,访问
// 不存在的实例变量时会导致 NoSuchMethodError 错误。
@override
void noSuchMethod(Invocation invocation) {
print('You tried to use a non-existent member: ' +
'${invocation.memberName}');
}
}
- 这样可以避免一些dynamic类型的实例对象类型错误,导致访问某些方法时崩溃问题;
-
Mixin
- 为类添加功能
用with关键词,类似于swift的协议 - class Maestro extends Person
with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
} - mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}- 指定类型的mixin
mixin MusicalPerformer on Musician {
// ···
}
- 为类添加功能
-
静态方法/类方法
- class Point {
num x, y;
Point(this.x, this.y);
static num distanceBetween(Point a, Point b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
} - class Point {
-
静态常量
- class Queue {
static const initialCapacity = 16;
// ···
}
- class Queue {
泛型
<T>表示
List<String> list = ['a', 'b'];
var list = <int>[0, 1, 2];
var map = <String, dynamic>{};
限制泛型类型
- class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}
泛型函数
- T aFunc<T>(T param){
}
库
import
- import 'dart:html';
import 'package:test/test.dart'; - 前缀
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// 使用 lib1 中的 Element。
Element element1 = Element();
// 使用 lib2 中的 Element。
lib2.Element element2 = lib2.Element();
- 导入一部分
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
- 延迟加载:让应用在需要的时候再加载库
import 'package:greetings/hello.dart' deferred as hello;
当需要使用的时候,使用库标识符调用 loadLibrary() 函数来加载库:
Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
在一个库上你可以多次调用 loadLibrary() 函数。但是该库只是载入一次。
export
library
part
异步
返回Future/Stream
async-await关键字
- Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
} - await 表达式会阻塞代码的执行,直到需要的对象返回为止。
Isolates
所有 Dart 代码都在隔离区( isolates )内运行,而不是线程。
每个隔离区都有自己的内存堆,确保每个隔离区的状态都不会被其他隔离区访问。
typedef
自定义函数类型
typedef NetworkRequestCompletion = void Function(Error error, Map<String, dynamic> json);
元数据
元数据注释以字符 @ 开头
/// Deprecated: Use [turnOn] instead.
@deprecated
void activate() {
turnOn();
}