1.特殊运算符
- ??=
//原来变量有值时??=不执行,当原来变量为null时将值赋值给这个变量
var name = null;
name ??= "lisi";
print(name); //输出结果lisi
var name = "a";
name ??= "lisi";
print(name); //输出结果a
- ??
// ??前面有值就使用??前面的值,??前面为null则使用??后面的值
var name = "a";
var temp = name ?? "lilei";
print(temp); //输出结果a
var name = null;
var temp = name ?? "lilei";
print(temp); //输出结果lilei
- ..(级联运算符),类似链式调用
void main(List<String> args) {
var dog = Dog()
..name = "xiaohuang"
..eat()
..run();
}
class Dog {
String? name;
void eat() {}
void run() {}
}
2.final和const的区别
const必须赋值,编译期间能确定的常量值
final可以通过函数获取,可以运行期间来确定的值
例子:
const data = DateTime.now() //错误,编译期间无法确定
final data = DateTime.now() //正确
3.集合类型
- 列表List
var list = ["123", "321", "11"];
- 集合Set
var set = {"123", "321", "11"};
- 映射Map
var map = {"name": "zhangsan", "age": 20};
4.函数参数
函数的参数可以分成两类: 必须参数和可选参数,前面使用的参数都是必选参数
Dart的函数不支持函数重载
- 必传参数
// 必选参数: 必须传 void say1(String name) { print(name); } say1("lisi");
- 位置可选参数
// 位置可以选参数,[]必须按照参数顺序传参,无需参数名 void say2(String name, [int age = 0, double height = 0]) { print(name); } say2("wangwu"); say2("zhangsan", 18); say2("zhangsan", 18, 1.88);
- 命名可选参数
// 命名可选参数,{}内参数无顺序要求,但是必须带上参数名 void say3(String name, {int age = 0, double height = 0}) { print(name); } say3("maliu"); say3("maliu", age: 18); say3("maliu", height: 1.88); say3("maliu", age: 18, height: 1.88);
5.构造方法
-
命名构造方法
因为Dart不支持函数的重载,所以我们没办法创建相同名称的构造方法,这时我们就需要使用命名构造方法
在实际开发中我们也可以使用命名构造函数来提供更加方便的创建对象方法:void main(List<String> args) { var a1 = Animal(); var a2 = Animal.withArgments("dog", 2); } class Animal { String? name; int? age; Animal() { name = ""; age = 0; } Animal.withArgments(String name, int age) { this.name = name; this.age = age; } }
Animal.fromMap(Map<String, Object> map) { this.name = map['name'] as String; this.age = map['age'] as int; } var a3 = Animal.fromMap({"name": "cat", "age": 10}); print("name is ${a3.name} age is ${a3.age}"); //输出结果name is cat age is 10
-
常量构造方法
在某些特定场景需要我们传入相同参数返回的对象是同一个,这时可以使用常量构造方法,常量构造方法的类中所有属性必须用final修饰,创建对象使用const关键字而不是new关键字void main(List<String> args) { var dog1 = Dog('xiaohua'); var dog2 = Dog('xiaohua'); print(identical(dog1, dog2)); //false var cat1 = const Cat("xiaohuang"); var cat2 = const Cat("xiaohuang"); var cat3 = const Cat("xiaohuang2"); print(identical(cat1, cat2)); //true print(identical(cat1, cat3)); //false } class Dog { String name; Dog(this.name); } class Cat { final String name; const Cat(this.name); }
-
工厂构造方法
如果一个构造函数并不总是返回一个新的对象,则使用 factory 来定义 这个构造函数。
如例子中创建2个名字为‘小黄’的Dog对象工厂返回的是同一个对象并没有创建新的对象。这里与其他构造方法的不同点:工厂方法必须有返回值,而构造方法是不能有返回值的.
void main(List<String> args) { var dog1 = Dog("小黄"); var dog2 = Dog("小黄"); var dog3 = Dog("小蓝"); print(identical(dog1, dog2)); //true print(identical(dog2, dog3)); //false } class Dog { String name; static final Map<String, Dog> _cache = <String, Dog>{}; factory Dog(String name) { if (_cache.containsKey(name)) { return _cache[name] as Dog; } else { final dog = Dog._internal(name); _cache[name] = dog; return dog; } } Dog._internal(this.name); }
-
重定向构造方法
一个构造函数调用另外一个构造函数(冒号后面使用this调用其他构造函数)void main(List<String> args) { var dog = Dog("xiaohuang", 2); var dog1 = Dog.fromMap({"name": "xiaoghuang2", "age": 12}); } class Dog { String name; int age; Dog(this.name, this.age); Dog.fromName(String name) : this(name, 0); Dog.fromMap(Map map) : this.fromName(map["name"]); }
6.setter和getter
void main(List<String> args) {
var dog = Dog("小黄");
dog.setName = "小黑";
print(dog.name);
dog.name = "小白";
print(dog.getName);
}
class Dog {
String name;
String get getName {
return name;
}
set setName(String name) {
this.name = name;
}
Dog(this.name);
}