【问题标题】:Method Overriding in Dart when the Return Type is "void"返回类型为“void”时 Dart 中的方法覆盖
【发布时间】:2020-12-19 14:38:18
【问题描述】:

在没有 正确(据我所知)返回类型的情况下覆盖 Dart 中的方法时,我预计会出现编译时错误。但是,当方法的返回类型为void 时,情况似乎有所不同:

abstract class AbstractClass {
  void methodDoesNotReallyReturnVoid();
}

class ConcreteClass extends AbstractClass {
  // NO ERROR here!
  @override
  int methodDoesNotReallyReturnVoid() => 12;
}

void main() {
  print(ConcreteClass().methodDoesNotReallyReturnVoid()); // hm...?
}

上面的代码可以毫无问题地编译并按预期打印整数,尽管我没有像在 Java 中那样正确覆盖该方法。

我可以知道这里的“无效”有什么不同吗?

【问题讨论】:

    标签: dart overriding void return-type


    【解决方案1】:

    @Ardent Coder's answer 引用了具体细节,但简短的版本是:

    int methodDoesNotReallyReturnVoid() 覆盖能否满足基本void methodDoesNotReallyReturnVoid() 方法的契约?是的,因为返回的值可以简单地忽略。

    【讨论】:

    【解决方案2】:

    这是结合Formal specification (Dart 2.2)的某些部分后的答案。

    首先,语言规范中定义了一些条件,以使方法成为正确的覆盖。在问题中描述的混淆范围内,这是重要的section

    如果 mm' 都是方法或两个 setter:设 F 是函数 m 的类型,除了参数类型是内置类 Object 对于具有修饰符协变的 m 的每个参数。让 F' 成为 m' 的函数类型。 F 必须是 F' 的子类型。

    这意味着所考虑的返回类型也可以是子类型。下面的代码sn -p就清楚了:

    abstract class AbstractClass {
      num methodReturnsNum();
    }
    
    class ConcreteClass extends AbstractClass {
      // No error here because int is a subtype of num
      @override
      int methodReturnsNum() => 12;
    }
    
    void main() {
      // Compiles and prints the integer.
      print(ConcreteClass().methodReturnsNum());
    }
    
    

    那么按照原来的问题,这是否意味着intvoid 的子类型?这对我来说是新的,the answer 是“是”:

    每个类型都是Object的子类型,每个类型都是dynamic的子类型, 每个类型都是 void 的子类型。请注意,这意味着这些 根据子类型关系,类型是等价的。

    因此,问题中的代码类似于:

    abstract class AbstractClass {
      Object methodReturnsObject();
    }
    
    class ConcreteClass extends AbstractClass {
      // No error here because int is a subtype of Object
      @override
      int methodReturnsObject() => 12;
    }
    
    void main() {
      // Compiles and prints the integer.
      print(ConcreteClass().methodReturnsObject());
    }
    
    

    针对惊喜元素,Void Soundness下的段有注释:

    特别是,我们可以要求方法覆盖不应该 通过返回类型 void 或参数类型覆盖返回类型 Object 反方向;带有类型参数 void 的参数化类型 无法分配给对应类型的变量 参数是 void 以外的任何东西,等等等等。但这将是 很不切实际。特别是,需要防止大 具有 void 值的类型变量的数量,或 防止某些类型的值使用这种类型 变量,或者其类型包含这样一个类型变量,这将是 严格限制了所有 Dart 代码的很大一部分。所以我们 已选择帮助开发人员保持这种自我强加的纪律 在简单直接的情况下,留给临时推理或 单独的工具以确保将间接情况涵盖为 根据实际需要密切配合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 2020-07-16
      • 1970-01-01
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多