java 抽象泛型,在Java中重写抽象泛型方法

Problem outline

I'm generifying the better part of my current project's base and I had an idea that I decided to test regarding overriding an abstract method. Here are my test classes in Java:

public abstract class Base {

public abstract T test();

}

First implementation:

public class Inheritor extends Base {

@Override

public Inheritor test() {

return null;

}

}

Second implementation:

public class Inheritor2 extends Base {

@Override

public T test() {

return null;

}

}

Question 1

Why does it compile? I admit I had high hopes it would be legal, since it makes the contract not only ensure it returns something that does extend Base, but is more specialized already (so that I don't need to cast the result to my specialized class somewhere later).

All sounds nice but do I really fulfill the contract that the base class forces me into? My overriden implementation in Inheritor loses certain layer of genericness doesn't it? My implementation of this method in Inheritor doesn't ever return an instance of Inheritor2, possibility of which the abstract method seemed to enforce (as both extend Base).

I would like pointing to some excerpt from documentation. My guess is it has something to do with type erasure, would be nice if someone mentioned it's accuracy in his/her answer.

Question 2

Does this procedure have a formal name other than one I stated in the title?

Question 3

Is this possible in C#? Colleague's scratch test seemed to fail on compilation. Is there then a difference in approach to generic abstract method overriding?

解决方案

Here are the technicalities.

Concerning 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.

[...]

In your case, A is Base and C is Inheritor, Base#test() is mA and Inheritor#test() is mC.

mC is a subsignature of 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.

The erasure of mA is

public abstract Base test()

and 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.

Following the return-type-substitutable, we see

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 is a subtype of T extends Base through unchecked conversion, so we're all good (though you should have gotten a warning from your compiler).

So to answer your questions:

It compiles because of the rules declared in the Java Language Specification.

It's called overriding.

I don't have a full answer for you, but C# doesn't seem to have type erasure, so these rules wouldn't apply.

The dangers of unchecked conversion would allow you to do

class Inheritor extends Base {

@Override

public Inheritor test() {

return new Inheritor();

}

}

and then

Base ref = new Inheritor();

Inheritor2 wrong = ref.test();

which would cause a ClassCastException at runtime. Use it at your own risk.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值