我对这里提到的工厂构造函数示例有些疑问(https://www.dartlang.org/guides/language/language-tour#factory-constructors)。我知道在基本级别上只有三种类型的构造函数-默认,命名和参数化。
Dav*_*ort 26
tl; dr在不一定要返回类本身的新实例的情况下使用工厂。用例:
说明
Dart类可以具有生成构造函数或工厂构造函数。生成构造函数是始终返回该类的新实例的函数。因此,它不使用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
Run Code Online (Sandbox Code Playgroud)
工厂构造函数比生成构造函数具有更宽松的约束。工厂只需要返回与该类相同类型或实现其方法(即满足其接口)的实例。这可能是该类的新实例,但也可能是该类的现有实例或子类的新实例/现有实例(其子类必定具有与父类相同的方法)。工厂可以使用控制流来确定要返回的对象,并且必须使用return
关键字。为了使工厂返回新的类实例,它必须首先调用生成的构造函数。
在您的示例中,未命名的工厂构造函数首先从一个名为的Map属性读取_cache
(由于它是Static
,因此存储在类级别,因此独立于任何实例变量)。如果实例变量已经存在,则将其返回。否则,将通过调用命名的生成构造函数来生成新实例Logger._internal
。缓存此值,然后返回。因为生成构造函数仅接受一个name
参数,所以该mute
属性将始终被初始化为false,但可以使用默认的setter进行更改:
var log = Logger("...");
log.mute = true;
log.log(...); // will not print
Run Code Online (Sandbox Code Playgroud)
该术语factory
暗指工厂模式,它的全部含义是允许构造函数根据提供的参数返回子类实例(而不是类实例)。Dart中此用例的一个很好的例子是抽象的HTML Element类,它定义了数十个返回不同子类的命名工厂构造函数。例如,分别Element.div()
与Element.li()
return <div>
和<li>
element。
在此缓存应用程序中,我发现“ factory”有点用词不当,因为其目的是避免调用生成的构造函数,并且我将现实世界中的工厂视为固有的生成。也许在这里更合适的术语是“仓库”:如果某件物品已经可用,请将其从货架上取下并交付。如果没有,请致电一个新的。
这与命名构造函数有何关系?生成构造函数和工厂构造函数都可以不命名,也可以命名:
...
// 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");
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*elo 25
补充戴夫的回答,此代码显示了使用工厂返回父相关类时的清晰示例。
从https://codelabs.developers.google.com/codelabs/from-java-to-dart/#3看一下这段代码
您可以在此处运行此代码。https://dartpad.dartlang.org/63e040a3fd682e191af40f6427eaf9ef
进行一些更改以了解它在某些情况下的工作方式,例如单身人士。
import 'dart:math';
abstract class Shape {
factory Shape(String type) {
if (type == 'circle') return Circle(2);
if (type == 'square') return Square(2);
// To trigger exception, don't implement a check for 'triangle'.
throw 'Can\'t create $type.';
}
num get area;
}
class Circle implements Shape {
final num radius;
Circle(this.radius);
num get area => pi * pow(radius, 2);
}
class Square implements Shape {
final num side;
Square(this.side);
num get area => pow(side, 2);
}
class Triangle implements Shape {
final num side;
Triangle(this.side);
num get area => pow(side, 2) / 2;
}
main() {
try {
print(Shape('circle').area);
print(Shape('square').area);
print(Shape('triangle').area);
} catch (err) {
print(err);
}
}
Run Code Online (Sandbox Code Playgroud)
Gün*_*uer 13
1)静态方法和工厂构造函数之间没有太大区别。
对于工厂构造函数,返回类型固定为类的类型,而对于静态方法,您可以提供自己的返回类型。
可以使用调用工厂构造函数new
,但new
在Dart 2中,该构造函数几乎与可选对象无关。
还有(工厂)构造函数支持的其他功能,如重定向(很少使用),但静态方法不支持。
使用工厂构造函数来创建类的实例而不是静态方法来使对象创建的目的更加明显可能仍然是一种好习惯。
这就是在您发布的示例中使用工厂构造函数的原因,并且可能是因为该代码最初是在Dart 1中编写的,它允许new
与其他任何类一样创建记录器实例。
2)是的,这是一个命名构造函数,并且前缀_
使它成为私有的命名构造函数。只能将命名构造函数设为私有,因为否则将无处添加_
前缀。
它用于防止从public factory构造函数以外的任何地方创建实例。这样可以确保Logger
您的应用程序中不能有多个实例。工厂构造函数仅在首次创建实例时使用,对于后续调用始终返回先前创建的实例。
除了其他答案之外,还要考虑实例化对象的顺序以及创建实例的时间:
在普通构造函数中,会创建一个实例,并使用初始化列表实例化最终变量。这就是没有return
声明的原因。执行构造函数时,返回的实例已经固定!
在工厂构造函数中,要返回的实例由方法决定。这就是为什么它需要一个return
语句以及为什么它通常会在至少一个路径中调用一个普通的构造函数。
因此,工厂所做的与静态方法所做的没有什么不同(在其他语言中通常称为getInstance()
),除非您不能使用静态方法重载构造函数,但可以使用工厂方法。即工厂方法是一种隐藏以下事实的方法:您的类的用户不是调用构造函数而是调用静态方法:
// C++
MyCoolService.getInstance()
// Dart
MyCoolService()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7198 次 |
最近记录: |