Dart 命名构造函数、静态方法和工厂构造函数
Dart named constructor, static method, and factory constructor
给定以下代码:
const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);
final myObject = MyClass.fromJson(jsonMap);
使用此语法创建新对象的方法有多少种:
MyClass.fromJson(jsonMap)
最近我一直在试图理解命名构造函数、工厂构造函数和静态方法之间的区别,所以我将我的答案贴在下面,以便我有一些东西可以作为参考未来。
使用以下语法创建对象的新实例:
MyClass.fromJson(jsonMap)
与以下代码一起使用:
// import 'dart:convert';
const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);
final myObject = MyClass.fromJson(jsonMap);
至少有以下几种方式可以做到(各有特点补充说明):
生成构造函数
class MyClass {
MyClass(this.myString);
final String myString;
MyClass.fromJson(Map<String, dynamic> json) : this(json['myString']);
}
有两种生成构造函数:命名和未命名。 MyClass.fromJson()
是命名构造函数,而 MyClass()
是未命名构造函数。以下原则适用于生成构造函数:
- 生成构造函数只能实例化 class 本身。
- 生成构造函数可以使用初始化列表。
- 生成构造函数只能使用初始化参数或初始化列表来设置
final
属性,即不能在构造函数体中。
- 生成构造函数可以是
const
,即使它们没有重定向。
工厂构造函数
class MyClass {
MyClass(this.myString);
final String myString;
factory MyClass.fromJson(Map<String, dynamic> json) {
return MyClass(json['myString']);
}
}
- 工厂构造函数可以 return class.
的子类型
- 工厂构造函数可用于创建单例。
- 工厂构造函数可以像生成构造函数一样未命名。
- 工厂构造函数可以是
const
,但仅在重定向时。
静态方法
class MyClass {
MyClass(this.myString);
final String myString;
static MyClass fromJson(Map<String, dynamic> json) {
return MyClass(json['myString']);
}
}
- 静态方法可以 return 任何东西,包括 Future。
- 静态方法可用于创建单例。
- 静态方法可以用作tear-offs。
进一步阅读
- The difference between a "factory constructor" and a "static method"
- dart advantage of a factory constructor identifier
另外还有@suragch 的详细回答。我想给出一些要点,表明 factory constructor
是上述场景的最佳选择(对于 fromJson() 方法)。
使用工厂构造函数时,不需要初始化 class 的实例变量。 (但是当你使用生成构造函数时,需要初始化所有的最终实例变量)
工厂构造函数可以return一个现有的对象。
例如:- 当使用 json_seriazible 包时,fromJson() 方法 return 一个现有的(以前创建的)对象。所以我们只能使用这个包的工厂构造函数。
工厂构造函数可以 return class 的任何 子类型 ,但是当使用生成构造函数时,它只能 return class.
的确切类型对象
确保只创建一个 class 实例(单例模式)。
(对象很昂贵,所以 fromJson 应该需要单例模式)
根据以上几点,我们可以看到生成构造函数为 fromJson 构造函数增加了更多限制,而静态方法为 fromJson 提供了更少的限制,因此它可以通过 return 不同类型的对象导致类型错误。
给定以下代码:
const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);
final myObject = MyClass.fromJson(jsonMap);
使用此语法创建新对象的方法有多少种:
MyClass.fromJson(jsonMap)
最近我一直在试图理解命名构造函数、工厂构造函数和静态方法之间的区别,所以我将我的答案贴在下面,以便我有一些东西可以作为参考未来。
使用以下语法创建对象的新实例:
MyClass.fromJson(jsonMap)
与以下代码一起使用:
// import 'dart:convert';
const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);
final myObject = MyClass.fromJson(jsonMap);
至少有以下几种方式可以做到(各有特点补充说明):
生成构造函数
class MyClass {
MyClass(this.myString);
final String myString;
MyClass.fromJson(Map<String, dynamic> json) : this(json['myString']);
}
有两种生成构造函数:命名和未命名。 MyClass.fromJson()
是命名构造函数,而 MyClass()
是未命名构造函数。以下原则适用于生成构造函数:
- 生成构造函数只能实例化 class 本身。
- 生成构造函数可以使用初始化列表。
- 生成构造函数只能使用初始化参数或初始化列表来设置
final
属性,即不能在构造函数体中。 - 生成构造函数可以是
const
,即使它们没有重定向。
工厂构造函数
class MyClass {
MyClass(this.myString);
final String myString;
factory MyClass.fromJson(Map<String, dynamic> json) {
return MyClass(json['myString']);
}
}
- 工厂构造函数可以 return class. 的子类型
- 工厂构造函数可用于创建单例。
- 工厂构造函数可以像生成构造函数一样未命名。
- 工厂构造函数可以是
const
,但仅在重定向时。
静态方法
class MyClass {
MyClass(this.myString);
final String myString;
static MyClass fromJson(Map<String, dynamic> json) {
return MyClass(json['myString']);
}
}
- 静态方法可以 return 任何东西,包括 Future。
- 静态方法可用于创建单例。
- 静态方法可以用作tear-offs。
进一步阅读
- The difference between a "factory constructor" and a "static method"
- dart advantage of a factory constructor identifier
另外还有@suragch 的详细回答。我想给出一些要点,表明 factory constructor
是上述场景的最佳选择(对于 fromJson() 方法)。
使用工厂构造函数时,不需要初始化 class 的实例变量。 (但是当你使用生成构造函数时,需要初始化所有的最终实例变量)
工厂构造函数可以return一个现有的对象。 例如:- 当使用 json_seriazible 包时,fromJson() 方法 return 一个现有的(以前创建的)对象。所以我们只能使用这个包的工厂构造函数。
工厂构造函数可以 return class 的任何 子类型 ,但是当使用生成构造函数时,它只能 return class.
的确切类型对象确保只创建一个 class 实例(单例模式)。 (对象很昂贵,所以 fromJson 应该需要单例模式)
根据以上几点,我们可以看到生成构造函数为 fromJson 构造函数增加了更多限制,而静态方法为 fromJson 提供了更少的限制,因此它可以通过 return 不同类型的对象导致类型错误。