问题概要
我正在生成我当前项目基础的更好部分,并且我有一个想法,我决定测试有关重写抽象方法的内容。这是我用 Java 编写的测试类:
public abstract class Base {
public abstract <T extends Base> T test();
}
第一次实现:
public class Inheritor extends Base {
@Override
public Inheritor test() {
return null;
}
}
第二次实现:
public class Inheritor2 extends Base {
@Override
public <T extends Base> T test() {
return null;
}
}
问题一
为什么编译?我承认我非常希望它是合法的,因为它使契约(Contract)不仅确保它返回确实扩展 Base 的东西,而且已经更加特化(这样我就不需要稍后将结果转换为我的专业类).
一切听起来不错,但我真的履行了基类强制我签订的契约吗?我在 Inheritor
中的覆盖实现失去了一定的通用性,不是吗?我在 Inheritor
中实现此方法从未返回 Inheritor2
的实例,抽象方法似乎强制执行的可能性(因为两者都扩展了 Base
).
我想指出文档中的一些摘录。我的猜测是它与类型删除有关,如果有人在他/她的回答中提到它的准确性,那就太好了。
问题二
除了我在标题中提到的以外,这个过程是否有正式名称?
问题三
这在 C# 中可行吗?同事的 scratch 测试似乎编译失败了。那么通用抽象方法重写的方法是否存在差异?
最佳答案
这是技术细节。
关于overriding :
An instance method
mC
declared in or inherited by classC
, overrides fromC
another methodmA
declared in classA
, iff all of the following are true:
A
is a superclass ofC
.C
does not inheritmA
.- The signature of
mC
is a subsignature (§8.4.2) of the signature ofmA
.- One of the following is true:
mA
ispublic
.- [...]
在你的例子中,A
是 Base
而 C
是 Inheritor
,Base#test( )
是 mA
而 Inheritor#test()
是 mC
。
mC
是 mA
的子签名 because
The signature of a method m1 is a subsignature of the signature of a method m2 if either: - m2 has the same signature as m1, or - the signature of m1 is the same as the erasure (§4.6) of the signature of m2.
mA
的删除是
public abstract Base test()
和mC
public Inheritor test()
是一个子签名。 What about the return type?
If a method declaration
d1
with return typeR1
overrides or hides the declaration of another methodd2
with return typeR2
, thend1
must be return-type-substitutable (§8.4.5) ford2
, or a compile-time error occurs.
按照return-type-substitutable
,我们看到
If R1 is a reference type then one of the following is true:
R1
can be converted to a subtype ofR2
by unchecked conversion (§5.1.9).
Inheritor
是 T extends Base
通过未经检查的转换的子类型,所以我们都很好(尽管您应该从编译器那里得到警告)。
所以回答你的问题:
- 它根据 Java 语言规范中声明的规则进行编译。
- 这叫做覆盖。
- 我没有完整的答案给你,但 C# 似乎没有类型删除,所以这些规则不适用。
未经检查的转换的危险会让你做
class Inheritor extends Base {
@Override
public Inheritor test() {
return new Inheritor();
}
}
然后
Base ref = new Inheritor();
Inheritor2 wrong = ref.<Inheritor2>test();
这会在运行时导致 ClassCastException
。使用它需要您自担风险。
关于java - 覆盖Java中的抽象泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27427798/