这是结合Formal specification (Dart 2.2)的某些部分后的答案。
首先,语言规范中定义了一些条件,以使方法成为正确的覆盖。在问题中描述的混淆范围内,这是重要的section:
如果 m 和 m' 都是方法或两个 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());
}
那么按照原来的问题,这是否意味着int 是void 的子类型?这对我来说是新的,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 代码的很大一部分。所以我们
已选择帮助开发人员保持这种自我强加的纪律
在简单直接的情况下,留给临时推理或
单独的工具以确保将间接情况涵盖为
根据实际需要密切配合。