dart - Dart:为什么继承的字段不能用作构造函数参数?
问题描述
以下代码将不会运行:
class X{
double? x;
}
mixin Y{
double? y;
}
class Z extends X with Y {
double? z;
Z(this.x, this.y, this.z)
}
编译器会抱怨 this.x 和 this.y 不是封闭类中的字段:
lib/physicalObject.dart:20:10: Error: 'x' isn't an instance field of this class.
Z(this.x, this.y, this.z)
^
lib/physicalObject.dart:20:18: Error: 'y' isn't an instance field of this class.
Z(this.x, this.y, this.z)
^
当然这不是真的,字段 x 和 y 是继承自父类和 mixin。我可以在子类 Z 中使用这些字段,似乎只有构造函数在接受这些作为参数时存在问题。但为什么?
解决方案
Dart 实例变量(又名“字段”)引入了一个存储单元、一个隐式 getter 和一个隐式 setter(除非变量 isfinal
和 not late
,则没有 setter)。
构造函数初始化器可以直接初始化存储单元,无需调用setter,即使没有setter。这就是做什么Z(this.z)
或Z(double? z) : this.z = z;
做的,它将一个值直接存储到实例变量的存储中。
像这样的构造函数Z(double? z) { this.z = z; }
不直接存储到单元格中,而是调用命名的设置器z=
,然后可能存储到(必须是非最终的或后期的)变量的存储中。或者它可能不会。Setter 是虚拟的,子类可以覆盖它们,并且{ this.z = z; }
赋值将调用被覆盖的 setter。
一般来说,子类看不到超类的变量,看到的只是超类的接口,只暴露了getter和setter。如果超类决定将字段声明更改为 getter 和 setter 声明对,那么他们可以. 它是非破坏性的,子类无法区分。所以,如果子类能以某种方式看到一个变量可以被初始化(不仅仅是分配给),那么我们就打破了这种对称性,并且超类被锁定为拥有一个可初始化的变量。
初始化必须在声明实例变量的类中进行,因为如果没有,我们会通过泄漏 getter/setter 是否由字段支持来破坏该类接口的抽象,然后我们将类锁定在该选择中. 这与为什么 Dart 拥有它所拥有的那种 getter/setter 声明完全相反,这就是让它成为一个实现选择,无论你使用一个还是另一个,而不是公共 API 选择。
推荐阅读
- javascript - Safari not loading javascript files from IIS on local network
- xcode - Breaking up one array into multiple arrays in Postman
- javascript - NodeJs Crypto - MD5 Hash is incorrect
- r - Returning Confidence Interval Results from rptR
- javascript - Finding min and max in array Javascript
- push - No manifest found when i run the Push demo code
- python - pyodbc procedure execute failure
- android - Maximum size for AppBundle for Playstore
- wireshark - 使用 scapy 和 wireshark 生成 STP 流量 [格式错误的数据包]
- javascript - SweetAlert 2 button cancel submitting form