关于这里提到的工厂构建器示例,我有一些棘手的问题(https://www.dartlang.org/guides/language/language-tour#factory-constructors). 我知道在基本级别上只有三种类型的构造函数-默认构造函数、命名构造函数和参数化构造函数.

  1. 为什么我要在这个例子中使用factory
  2. 正在使用的是命名构造函数吗?为什么? Example factory constructor

推荐答案

tl;dr在您不希望necessarily返回类本身的new实例的情况下使用工厂.使用 case :

  • 构造函数的开销很大,所以如果可能的话,您希望返回一个现有实例,而不是创建一个新实例;
  • 您只想创建一个类的一个实例(单例模式);
  • 您希望返回子类实例,而不是类本身.

Explanation

Dart类可能有generative constructorsfactory constructors.个生成构造函数,它是一个总是返回类的新实例的函数.因此,它不使用return关键字.常见的生成构造函数的形式如下:

class Person {
  String name;
  String country;

  // unnamed generative constructor
  Person(this.name, this.country);
}
var p = Person("...") // returns a new instance of the Person class

工厂构造器比生成构造器有更宽松的约束.工厂只需要返回一个与类类型相同或实现其方法(即满足其接口)的实例.这可能是类的新实例,但也可能是类的现有实例或子类的新/现有实例(必须与父类具有相同的方法).工厂可以使用控制流来确定要返回的对象,并且必须使用return关键字.为了让工厂返回新的类实例,它必须首先调用生成构造函数.

Dart Factory Explained

在您的示例中,未命名的工厂构造函数首先读取名为_cache的映射属性(因为它是Static,所以存储在类级别,因此独立于任何实例变量).如果实例变量已经存在,则返回它.否则,通过调用命名的生成构造函数Logger._internal生成新实例.该值将被缓存,然后返回.由于生成构造函数只接受name参数,因此mute属性将始终初始化为false,但可以使用默认setter进行更改:

var log = Logger("...");
log.mute = true;
log.log(...); // will not print

factory一词暗指工厂模式,它是关于允许构造函数根据提供的参数返回子类实例(而不是类实例).Dart中这个用例的一个很好的例子是抽象HTML Element class,它定义了几十个返回不同子类的命名工厂构造函数.例如,Element.div()Element.li()分别返回<div><li>个元素.

在这个缓存应用程序中,我发现"工厂"这个词有点用词不当,因为它的目的是避免调用生成性构造函数,而且我认为现实世界中的工厂本质上是生成性的.也许这里更合适的术语应该是"仓库":如果一件商品已经可以买到,就把它从货架上取下来,然后送货.如果没有,就叫一个新的.

所有这些与命名构造函数有何关系?生成构造函数和工厂构造函数都可以是未命名的,也可以是命名的:

...
  // named generative
  // delegates to the default generative constructor
  Person.greek(String name) : this(name, "Greece"); 

  // named factory 
  factory Person.greek(String name) {
    return Greek(name);
  }
}

class Greek extends Person {
  Greek(String name) : super(name, "Greece");
}


Dart相关问答推荐

Dart 3.3接口字段类型升级不起作用

将Card添加到 ListView

跳过 JavaScript 直接进入 Dart

可调用云函数错误:响应缺少数据字段

如何调整ShowDialog的子级大小

如何在Flutter中返回异步函数的值?

如何使我的对话框可滚动?

Flutter ToggleButton 类 - Flutter 1.9.1

iOS 上 Flutter 的代码设计错误

Flutter 中 ChangeNotifier 的构建器小部件

如何将整数中的ascii值转换为Flutter中的等效字符?

我们如何在 Dart 中删除一个对象?

如何在 Dart 2 中将 List 更改为 List

如何在 Dart 中以正确的方式重定向和重新加载?

在我的 angular-cli 元素中从 node-sass 切换到 dart sass

学习 Dart 好还是我必须使用基本的 javascript?

Dart 中使用的包命名约定是什么?

如何将 `ByteData` 实例写入 Dart 中的文件?

dart中的动态和对象有什么区别?

如何用 Dart 格式化日期?