【问题标题】:"'Class.field=' isn't a valid override" when overriding a field with a more specific type“'Class.field=' 不是有效的覆盖”当覆盖具有更具体类型的字段时
【发布时间】:2021-08-29 07:20:34
【问题描述】:
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 ?)) 不是 'Ainterface.list=' ('void Function(List?)') 的有效覆盖。

我想知道如何解决这个问题。我很无奈

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    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&lt;ObjB?&gt;? 可以替代List&lt;Binterface?&gt;?,反之亦然:List&lt;Binterface?&gt;? 不能 替代List&lt;ObjB?&gt;?,这就是的重要方向二传手.

    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&lt;AnotherB&gt;,即使ObjA.list 期望List&lt;ObjB&gt;,如果您尝试将a.list 用作List&lt;ObjB&gt;,最终会在运行时出错。

    如果你可以从逻辑上保证上述情况永远不会发生,那么你可以使用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;
      }
      

    我还要指出 overriding fields is usually a bad idea,而且您通常应该明确地覆盖 getter 和 setter。

    【讨论】:

      【解决方案2】:

      Ainterface 抽象类中,您声明应该声明类型为Binterface 的列表,因此任何扩展该类的类都应该这样做。所以当你想声明一个扩展这个类的类时,你应该考虑这一点。如果您还想声明 ObjB 类型的列表,则可以在此之后进行。会是这样的:

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

      【讨论】:

      • 我想知道为什么objb继承了列表中的bInterface ?列表会提示不是有效的覆盖希望大家帮我解决疑惑,谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2023-03-08
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多