2014-11-24 91 views
0

假设我有一个界面如下:接口,泛型和协变返回类型

public interface Foo<T> { 
    T doSomething(); 
} 

现在,都在下面允许吗?

public class Bar implements Foo<Number> { ... } 

public class Bar2 extends Bar implements Foo<Integer> { ... } 

一方面,我似乎不这么认为,因为Bar2“工具Foo两次”,即使IntegerNumber一个子类。另一方面,这不是doSomething()协变返回类型的情况吗?还是编译器不够聪明来检测?

+4

“_Now,都允许以下内容吗?_”你不能只是尝试运行这些东西,看看? – csmckelvey 2014-11-24 06:27:09

+1

'Foo '必须是'接口'而不是'类' – Jens 2014-11-24 06:27:38

+0

我不知道为什么这个问题有负面投票?这个问题的人正在清除我的概念。 – 2014-11-24 07:13:34

回答

0

这不是一个接口,这似乎是一个类(或抽象类,也缺少关键字abstract),它应该是这样的: -

public interface Foo<T> { 
     T doSomething(); 
} 

除了

public class Bar implements Foo<Number> { ... } 

public class Bar2 extends Bar implements Foo<Integer> { ... } 

会给你编译时间的错误, The interface Foo cannot be implemented more than once with different arguments: Foo<Number> and Foo<Integer>

但是,如果你改为: -

public class Bar implements Foo<Integer> { ... } 

public class Bar2 extends Bar implements Foo<Integer> { ... } 

这不会给一个编译时错误,如果你在BAR2实现doSomething()它会考虑到这一点,当你做: -

Bar2 bar2=new Bar2(); 
bar2.doSomething(); 

否则它将从Bar

运行 doSomething()

,显然,如果你这样做: -

Bar bar=new Bar(); 
bar.doSomething(); 

它会考虑到的Bar考虑doSomething(),因为它只有一个执行doSomething()到了这时候,即Bar(你有因为Bar实施是实现该接口Foo :))

2

如果Foo意味着是一个接口:

一个类不能同时是两个接口类型的子类型,它们是同一个通用接口[...]的不同参数化,或者发生编译时错误。

所以没有。 (JLS 8.1.5

而且它无论如何都没有意义,因为无论如何Bar恰好会从doSomething返回。也许这是一个Double

在另一方面,你可能还是会这么做:

class Bar2 extends Bar { 
    @Override 
    public Integer doSomething() {...} 
} 

或者是编译器没有足够的智慧来检测这样?

我们和编译器认为在这里并不重要。编译器绑定到规定错误的语言规范。