"'Class.field=' 不是有效的覆盖",当使用更具体的类型覆盖字段时


abstract class Ainterface {
String? name;
List<Binterface?>? list;
}
abstract class Binterface {
String? age;
int? len;
}
class ObjA extends Ainterface {
String? name;
List<ObjB?>? list;
ObjA({this.name, this.list});
}
class ObjB extends Binterface {
String? age;
int? len;
ObjB({this.age, this.len});
}

我使用objb作为列表中每个项目的类型,但是编辑器给出了一个错误'obja '。List =' (') void function (List <objb吗?>?))不是对' interface '的有效覆盖。= '列表("void函数(List<Binterface祝辞?)")。>

我怎样才能解决这个问题?

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?>?,这是setter重要的方向。

ObjA中的listsetter不是Ainterface中相应setter的安全重写,因为它将允许调用者违反其契约。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关键字,您有责任确保您在实践中不违反合同。

另外:

  • 重新考虑你的抽象基类是否需要将setter作为其接口的一部分公开,如果可能的话只公开getter。
  • 使Ainterface成为一个泛型类,参数化Binterface的具体类型:
    abstract class Ainterface<DerivedB extends Binterface> {
    List<DerivedB?>? list;
    }
    class ObjA extends Ainterface<ObjB> {
    List<ObjB?>? list;
    }
    

我还会指出覆盖字段通常是一个坏主意,无论如何,您通常应该显式地覆盖getter和setter。

Ainterface抽象类中,您声明应该将列表声明为Binterface类型,因此任何扩展该类的类都应该这样做。所以当你想要声明一个类来扩展这个类时,你应该考虑到这一点。如果你还想从ObjB类型声明一个列表,你可以在那之后做。它将像这样:

class ObjA extends Ainterface {
String? name;
List<Binterface?>? list;
List<ObjB ?>? list2;
ObjA({this.name, this.list, this.list2});
}

最新更新