java 抽象泛型方法_覆盖Java中的抽象泛型方法

问题概述

我正在扩大我当前项目基础的大部分内容,并且我有一个想法,我决定就覆盖抽象方法进行测试。这是我在Java中的测试类:

public abstract class Base {

public abstract T test();

}

第一次执行:

public class Inheritor extends Base {

@Override

public Inheritor test() {

return null;

}

}

第二实施:

public class Inheritor2 extends Base {

@Override

public T test() {

return null;

}

}

问题1

为什么编译?我承认我寄予很高的希望,因为它使合同不仅确保它返回可以扩展Base的东西,而且已经更加专业化(这样我以后就不必将结果投射到我的专业课上了) )。

听起来不错,但我真的履行了基层强迫我签订的合同吗?我在Inheritor中重写的实现失去了某些通用性,不是吗?我在Inheritor中对该方法的实现永远不会返回Inheritor2的实例,该实例可能会强制使用抽象方法(因为两者都扩展了Base)。

我想指出一些文档摘录。我的猜测是它与类型擦除有关,如果有人在回答中提到它的准确性,那就太好了。

问题2

除了我在标题中所说的以外,此过程是否具有正式名称?

问题3

这在C#中可能吗?同事的暂存测试似乎在编译时失败。那么通用抽象方法重写的方法是否有所不同?

什么是问题1? 2.其覆盖方法。 3.我相信艾伦·图灵说是的。

如果这被称为覆盖方法,并且上面的示例似乎未在C#中编译,则从形式上正式意味着C#不支持覆盖方法。

Java不是C#。 是的,在Java中,这是重写方法。

剩下的问题是是否有可能在C#中重现以及第一个问题(主要是关于失去通用性)

这里是技术。

关于覆盖:

An instance method mC declared in or inherited by class C, overrides

from C another method mA declared in class A, iff all of the following

are true:

A is a superclass of C.

C does not inherit mA.

The signature of mC is a subsignature (§8.4.2) of the signature of mA.

One of the following is true:

mA is public.

[...]

在您的情况下,A是Base,C是Inheritor,Base#test()是mA,Inheritor#test()是mC。

mC是mA的子签名,因为

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()

是一个子签名。那返回类型呢?

If a method declaration d1 with return type R1 overrides or hides the

declaration of another method d2 with return type R2, then d1 must be

return-type-substitutable (§8.4.5) for d2, 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 of R2 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.test();

这会在运行时导致ClassCastException。需要您自担风险使用它。

惊人的答案。 谢谢您为我指出了有关返回类型可替换性的规则,这正是我想要了解的。 同样,这是未经检查的转换,这也充分说明了IntelliJ IDEA为什么对我所做的事情感到脾气暴躁,谢谢您举一个滥用示例。 还不知道C#没有类型擦除,这就是为什么发生这种情况。 感谢您提供了确实有据可查的答案!

我可以告诉您为什么它应该起作用-Liskov替代原理

要问的问题是,如果将Base替换为Inheritor或Inheritor2,是否所有使用者都可以继续工作而不会带来负面影响?如果他们期望从test扩展Base的任何东西,那么从消费者的角度来看,将Inheritor2与Inheritor交换,反之亦然,就可以了。因此,编译器应该允许它。

您确实履行了合同,该合同规定可以返回任何Base子类型。任何子类型都可以是一个子类型,随机子类型等。

像评论员艾略特(Elliott)一样,我相信这只是所谓的覆盖方法。

这是C#中的类似实现,但在类级别具有泛型。

public abstract class Base

where Type : Base

{

public abstract Type test();

}

public class Inheritor:Base

{

public override Inheritor test()

{

return null;

}

}

public class Inheritor2 : Base

where Type : Base

{

public override Type test()

{

return default(Type);

}

}

您的C#示例将类型参数放置在类级别而不是方法级别。 我认为那有很大的不同。

确实如此。 。 。 让我看看是否可以在方法级别上解决该问题。

以为合同说:"您应该确切地归还我可以归还的东西,别无所求",这并不是因为第一个实现的通用性要差得多。 猜猜这就是混乱的来源。 我仍然对该C#版本感兴趣。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值