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。

进一步阅读

另外还有@suragch 的详细回答。我想给出一些要点,表明 factory constructor 是上述场景的最佳选择(对于 fromJson() 方法)。

  • 使用工厂构造函数时,不需要初始化 class 的实例变量。 (但是当你使用生成构造函数时,需要初始化所有的最终实例变量)

  • 工厂构造函数可以return一个现有的对象。 例如:- 当使用 json_seriazible 包时,fromJson() 方法 return 一个现有的(以前创建的)对象。所以我们只能使用这个包的工厂构造函数。

  • 工厂构造函数可以 return class 的任何 子类型 ,但是当使用生成构造函数时,它只能 return class.

    的确切类型对象
  • 确保只创建一个 class 实例(单例模式)。 (对象很昂贵,所以 fromJson 应该需要单例模式)

根据以上几点,我们可以看到生成构造函数为 fromJson 构造函数增加了更多限制,而静态方法为 fromJson 提供了更少的限制,因此它可以通过 return 不同类型的对象导致类型错误。