Dart 中的字段(数据成员)隐式提供 getter 和 setter 作为接口的一部分。因此,当你写:
abstract class Ainterface {
List<Binterface?>? list;
}
接口是隐式的:
abstract class Ainterface {
List<Binterface?>? get list;
set list(List<Binterface?>? value);
}
问题是你的派生类想要提供一个接口:
class ObjA extends Ainterface {
List<ObjB?>? get list;
set list(List<ObjB?>? value);
}
即使List<ObjB?>? 可以替代List<Binterface?>?,反之亦然:List<Binterface?>? 不能 替代List<ObjB?>?,这就是的重要方向二传手.
ObjA 中的 list 设置器不是来自Ainterface 的相应设置器的安全覆盖,因为它会允许调用者违反其合同。 Ainterface.list 宣传它允许设置为Binterface 的任何 实例,但ObjA.list 期望仅 是ObjB 的实例。举个具体的例子,如果允许覆盖,那么下面的代码编译不会出错:
class AnotherB extends Binterface {}
void main() {
Ainterface a = ObjA();
a.list = [AnotherB()]; // This error would not be caught at compile-time.
}
现在a.list 包含List<AnotherB>,即使ObjA.list 期望List<ObjB>,如果您尝试将a.list 用作List<ObjB>,最终会在运行时出错。
如果你可以从逻辑上保证上述情况永远不会发生,那么你可以使用covariant关键字来放松静态类型检查并允许覆盖:
abstract class Ainterface {
covariant List<Binterface?>? list;
}
但我再次强调,上面的代码删除了一些类型安全。通过使用covariant 关键字,您有责任确保您在实践中不违反合同。
或者:
我还要指出 overriding fields is usually a bad idea,而且您通常应该明确地覆盖 getter 和 setter。