在Java中重写抽象泛型方法
问题大纲 我正在泛化当前项目基础的更好部分,我有一个想法,我决定测试覆盖抽象方法。以下是我的Java测试类:在Java中重写抽象泛型方法,java,generics,abstract,overriding,Java,Generics,Abstract,Overriding,问题大纲 我正在泛化当前项目基础的更好部分,我有一个想法,我决定测试覆盖抽象方法。以下是我的Java测试类: public abstract class Base { public abstract <T extends Base> T test(); } 第二次执行: public class Inheritor extends Base { @Override public Inheritor test() { return nul
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;
}
}
公共类继承器2扩展了基{
@凌驾
公共T检验(){
返回null;
}
}
问题1
它为什么要编译?我承认我对它的合法性寄予厚望,因为它使合同不仅能够确保它返回的东西确实扩展了基础,而且已经更加专业化了(这样我就不需要在以后的某个地方将结果投射到我的专业类中)
听起来不错,但我真的履行了底层阶级强迫我履行的契约吗?我在Inheritor
中重写的实现失去了某种通用性,不是吗?我在Inheritor
中对该方法的实现从未返回Inheritor2
的实例,抽象方法可能会执行该实例(因为两者都扩展了Base
)
我想指出文件中的一些摘录。我的猜测是它与类型擦除有关,如果有人在他/她的答案中提到它的准确性,那就好了
问题2
这个程序是否有一个正式名称,而不是我在标题中所述的名称
问题3
这在C#中可能吗?这位同事的划痕测试在编译时似乎失败了。那么,泛型抽象方法重写的方法是否有所不同 我可以告诉你为什么它会起作用- 要问的问题是,如果将Base替换为Inheritor或Inheritor2,是否所有的使用者都会继续工作而不会产生负面后果?如果他们希望从
test
中扩展Base,那么从使用者的角度来看,将Inheritor2与Inheritor交换,或者反之亦然。因此,编译器应该允许它
您确实履行了合同,其中规定可以返回Base
的任何子类型。任何子类型都可以是一个子类型、随机子类型等
就像评论员Elliott一样,我相信这只是所谓的重写方法
这里有一个类似的C#实现,但在类级别上有泛型
public abstract class Base<Type>
where Type : Base<Type>
{
public abstract Type test();
}
public class Inheritor:Base<Inheritor>
{
public override Inheritor test()
{
return null;
}
}
public class Inheritor2<Type> : Base<Type>
where Type : Base<Type>
{
public override Type test()
{
return default(Type);
}
}
公共抽象类基类
其中类型:Base
{
公共抽象类型测试();
}
公共类继承器:基
{
公共重写继承器测试()
{
返回null;
}
}
公共类继承器2:基
其中类型:Base
{
公共重写类型测试()
{
返回默认值(类型);
}
}
以下是技术细节
关于:
类C
中声明或继承的实例方法mC
,重写
从C
类A
中声明的另一种方法mA
,如果满足以下所有条件
是真的:
是A
的超类C
不继承C
mA
的签名是mC
签名的子签名(§8.4.2)mA
- 以下情况之一是正确的:
是mA
public
- [……]
A
是Base
和C
是Inheritor
,Base#test()
是mA
和Inheritor#test()
是mC
mC
是mA
方法m1的签名是方法m1的签名的子签名
方法m2,如果:
-m2与m1具有相同的签名,或
-m1的签名与m2签名的删除(§4.6)相同。
mA
的擦除为
public abstract Base test()
和mC
public Inheritor test()
这是一个附属机构
如果返回类型为R1的方法声明覆盖或隐藏
另一个返回类型为R2
的方法d2
的声明,则必须是d1
对于d2
,或编译时错误
发生
在返回类型substitutable
之后,我们看到
如果R1是引用类型,则以下情况之一为真:
可以通过未经检查的转换(§5.1.9)转换为R1
的子类型R2
Inheritor
是T通过未经检查的转换扩展Base
的子类型,因此我们都很好(尽管您应该从编译器得到警告)
因此,要回答您的问题:
未经检查的转换的危险将允许您这样做
class Inheritor extends Base {
@Override
public Inheritor test() {
return new Inheritor();
}
}
然后
Base ref = new Inheritor();
Inheritor2 wrong = ref.<Inheritor2>test();
Base ref=new Inheritor();
继承人2错误=参考测试();
这将在运行时导致
ClassCastException
。使用风险自负。问题1是什么?2.它正在重写一个方法。3.我相信Alan Turing说是的。如果这被称为重写方法,而上面的示例似乎不是用C#编译的,那么它的正式意思是C#不支持重写方法。Java不是C#。是的,在Java中就是这样。这就留下了一个问题:是否可以在C#中重现,第一个问题(主要是关于失去泛型性)C#示例将类型参数放在类级别而不是方法级别。我想这会有很大的不同。真的。让我看看我是否能在方法层面上找到解决的方法。我想合同上说:“你应该准确地返回我能返回的东西,而不是更少”,w