【问题标题】:Dart named constructor, static method, and factory constructorDart 命名构造函数、静态方法和工厂构造函数
【发布时间】:2020-08-07 03:38:38
【问题描述】:

给定以下代码:

const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);

final myObject = MyClass.fromJson(jsonMap);

有多少种方法可以使用这种语法创建一个新对象:

MyClass.fromJson(jsonMap)

最近我一直在尝试理解命名构造函数、工厂构造函数和静态方法之间的区别,所以我在下面发布了我的答案,以便将来有一些东西可以作为参考。

【问题讨论】:

    标签: dart constructor static-methods


    【解决方案1】:

    使用以下语法创建对象的新实例:

    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() 是未命名构造函数。以下原则适用于生成构造函数:

    • 生成式构造函数只能实例化类本身。
    • 生成式构造函数可以使用初始化列表。
    • 生成式构造函数只能使用初始化参数或初始化列表设置final属性,即不能在构造函数体中。
    • 生成式构造函数可以是const,即使它们没有重定向。

    工厂构造函数

    class MyClass {
      MyClass(this.myString);
      final String myString;
    
      factory MyClass.fromJson(Map<String, dynamic> json) {
        return MyClass(json['myString']);
      }
    }
    
    • 工厂构造函数可以返回类的子类型。
    • 工厂构造函数可用于创建单例。
    • 工厂构造函数可以像生成构造函数一样不命名。
    • 工厂构造函数可以是const,但只能在重定向时使用。

    静态方法

    class MyClass {
      MyClass(this.myString);
      final String myString;
    
      static MyClass fromJson(Map<String, dynamic> json) {
        return MyClass(json['myString']);
      }
    }
    
    • 静态方法可以返回任何东西,包括 Future。
    • 静态方法可用于创建单例。
    • 静态方法可用作撕下。

    进一步阅读

    【讨论】:

    • Named constructors may only use the initializer list to set final properties. 是什么意思?即使使用像MyClass.named(this.myString) 这样的命名构造函数,您也可以初始化最终属性。您也可以使用 factory 构造函数创建单例,例如 here
    • @Mattia,感谢您指出这一点。我的意思是不能在命名构造函数体中设置最终属性,但我不够具体。我更新了我的答案。关于单身人士,我已经提到过。 (但是,将它放在静态方法下也可能使它看起来是创建单例的唯一方法。是这样吗?)
    • @lrn 我的印象是生成构造函数是没有名称的构造函数,即仅使用类名的构造函数。这不是真的吗?
    • @lrn 我在这里更详细地问了我的问题:stackoverflow.com/questions/63313102/…
    • 在那里回答,但不,这不是真的。生成或工厂与是否命名是正交的。工厂构造函数是那些以factory 为前缀的构造函数,其余的都是生成的。可以命名也可以不命名。
    【解决方案2】:

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

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

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

    • 工厂构造函数可以返回该类的任何子类型,但在使用生成构造函数时,它只能返回该类的确切类型对象。

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

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

    【讨论】:

    • 对于您的第 4 点,我会说它 可以 用于创建单例。但是,工厂构造函数也可以用于每次创建一个新对象。
    • @Suragch [如果工厂构造函数返回一个现有对象 => 单例模式 True(第 4 点是正确的。)] [但是如果工厂构造函数返回构造函数调用(创建一个新实例)=> 单例模式 False (第 4 点不正确。)我认为这就是您要说的重点。我说的对吗?
    猜你喜欢
    • 2014-02-18
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多