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

标签 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 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 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.
    • [...]

在你的例子中,ABaseCInheritorBase#test( )mAInheritor#test()mC

mCmA 的子签名 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 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).

InheritorT extends Base 通过未经检查的转换的子类型,所以我们都很好(尽管您应该从编译器那里得到警告)。

所以回答你的问题:

  1. 它根据 Java 语言规范中声明的规则进行编译。
  2. 这叫做覆盖。
  3. 我没有完整的答案给你,但 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/

相关文章:

java - EJB 计时器是否应该持久/可靠?

java - 发送到 ServerHandler 外部时,客户端未收到服务器发送的消息

c# - 嵌套接口(interface) : Cast IDictionary<TKey, IList<TValue>> 到 IDictionary<TKey, IEnumerable<TValue>>?

swift - 如何在 Swift 中使用类型删除静态访问泛型子类型?

c# - 如何创建一个可以访问创建它的类的成员的嵌套类?

java - 有没有办法使用 jersey 和 guice 处理 url 开头的额外斜杠?

java - session 属性访问并转换为 int?

c# - 使用反射查找通用列表元素的继承属性

.net - 获取 ADO.NET 中的参数前缀

c# - 重写抽象方法时,我重新设置抽象是否正确?