Dart中的构造函数有4种,分别是:
普通构造函数可以分为无参构造函数和有参构造函数。
如果不声明构造函数,则dart会提供一个默认的无参构造函数。当然,也可以自己定义有参构造函数,如果自己写了构造函数,那么默认构造函数就不存在了。
我们可以这么来定义一个有参构造函数
class People{
int? age;
String? name;
People(int age, String name){
this.age = age;
this.name = name;
}
}
这种赋值方式如果变量很多的话写起来比较麻烦,所以dart提供了语法糖来简化,直接在参数列表上这么写:
class People{
int? age;
String? name;
People(this.age, this.name);
}
注意:
如果想设置不同的参数可通过可选参数列表来设置:
class People{
int? age;
String? name;
People({this.age, this.name});
}
这种写法涵盖了这么几种形式:
People();
People(this.age);
People(this.name);
People(int age, String name);
class Child extends People{
Child(int age, String name): super(age: age, name: name);
// Child(int age, String name); 若父类为无参构造函数时则可以省略super调用
}
格式:类名.构造函数名
class People{
int? age;
String? name;
People.fromMap(Map map){
this.age = map["age"];
this.name = map["name"];
}
}
使用命名构造函数可为一个类实现多个构造函数,但是同样是不能重载。
如果一个里只有命名构造函数,那么子类需要显示调用父类的命名构造函数。
class B extends People{
B(Map map) : super.fromJson(map);
}
否则会报错
除了调用父类的构造函数,你还可以在执行构造函数体及调用父类构造函数之前初始化实例变量,使用逗号分隔每个初始化变量。
class Employee extends People {
int? no;
String? job;
String? address;
int? age1;
Employee(this.job, this.address, int? age)
: this.no = 123456,
age1 = age ?? 25,
super(age: age);
}
调用的顺序如下:
参数列表对于初始化那些final修饰的成员变量很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了。
注意:
定义构造函数的时候,除了可以定义一个普通构造函数之外,还可以定义若干个命名构造函数,这些构造函数之间,有时候会有一些相同的逻辑,如果分别写在各个构造函数中,会显得有些多余,所以构造函数可以传递。传递构造函数是没有方法体的,可以在初始化列表中,调用另一个构造函数。
class Point {
final num x;
final num y;
final num area;
Point(x, y)
: this.x = x,
this.y = y,
this.area = x * x + y * y;
Point.alongXAxis(num x) : this(x, 0);
}
如果生成类的对象是不会变的,可以定义常量构造函数(如果你的类,创建的对象永远不会改变,你可以在编译期就创建这个常量实例,并且定义一个常量构造函数,并且确保所有的成员变量都是final的。)。
class Point {
final num x;
final num y;
final num area;
const Point(x, y)
: this.x = x,
this.y = y,
this.area = x * x + y * y;
}
在使用时需注意:
有时候可能有一种需求,并不需要每次都创建新的类实例,而是每一种情况,只需要一个实例,这时候工厂构造函数就派上用场了。
工厂构造函数使用关键字factory来定义,factory可以放在类名函数之前,也可以放在命名函数之前。
使用场景:
class Logger {
final String name;
bool mute = false;
// _cache 变量是库私有的,因为在其名字前面有下划线。
static final Map _cache =
{};
factory Logger(String name) {
return _cache.putIfAbsent(
name, () => Logger._internal(name)); //工厂构造函数里可以调用其他构造函数。
}
factory Logger.fromJson(Map json) {
return Logger(json['name'].toString());
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
abstract class Animal {
String? name;
void getNoise();
factory Animal(String type, String name) {
switch (type) {
case "cat":
return new Cat(name);
case "dog":
return new Dog(name);
default:
throw "The '$type' is not an animal";
}
}
}
class Cat implements Animal {
String? name;
Cat(this.name);
@override
void getNoise() {
print("${this.name}: 喵~");
}
}
class Dog implements Animal {
String? name;
Dog(this.name);
@override
void getNoise() {
print("${this.name}: 旺~");
}
}
void main() {
var cat = new Animal("cat", "花花");
var dog = new Animal("dog", "小黑");
cat.getNoise(); // 花花: 喵~
dog.getNoise(); // 小黑: 旺~
}
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
void main() {
var s1 = Singleton();
var s2 = Singleton();
print(identical(s1, s2)); // true
}
注意: