Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:超类的通用接口_Java_Generics_Interface - Fatal编程技术网

Java:超类的通用接口

Java:超类的通用接口,java,generics,interface,Java,Generics,Interface,想象一下下面的代码: class A {} class B extends A {} interface IA extends Iterable<A> {} interface IB extends Iterable<B> {} 甚至 interface IB extends Iterable<B> implements IA {} 接口IB扩展了Iterable实现IA{} 但是,编译器确实不喜欢这两种类型,如果允许这样做,那么我的代码会更好,因为概

想象一下下面的代码:

class A {}
class B extends A {}

interface IA extends Iterable<A> {}
interface IB extends Iterable<B> {}
甚至

interface IB extends Iterable<B> implements IA {}
接口IB扩展了Iterable实现IA{}
但是,编译器确实不喜欢这两种类型,如果允许这样做,那么我的代码会更好,因为概念上B可以用作A,而无需到处上转换


我有什么解决方案可以解决这个问题呢?

Java中的泛型不是协变的——也就是说,
List instanceof List
为false。因此,
IB
不是
IA
的一个实例,因此我相信这是导致编译器问题的原因

想象一个新类,
类C扩展了{}
。C是A,因此C将是IA要包含的合法值,但不是IB。因此,如果您尝试将IB用作IA实例,则可能插入C并破坏类型安全保证。

这意味着您想要的内容不可行(至少在一般情况下不可行)

然而,也许能解决你的具体问题?e、 g

void methodThatOperatesOnA(Iterable<? extends A> it) {
    ...
}

void方法OperateSona(IterableA类型不能有两个超级类型
G和G,其中X!=Y
——可能是由于擦除

解决问题的一种方法是对要迭代的类型使用类型参数

interface IA<X extends A> extends Iterable<X>
{
    @Override Iterator<X> iterator();
}
interface IB extends IA<B>
{
    @Override Iterator<B> iterator();
}
这样会更好吗

public interface Iterable<T> 

    Iterator<? extends T> iterator();
公共接口不可编辑

迭代器很难看出这有什么用处;假设您想要的东西是可能的,您可以添加一个您想如何使用
IB
的示例吗?大图:
A
是用户,
B
是管理员。
IA
列出来自不同来源的用户,IB列出来自其他来源的管理员。当我使用
IB
我也希望能够将它传递给那些期望
IA
s的函数,因为它们是兼容的。是的。我该如何解决它或提供更好的API?我假设这就是原因,问题是如何修复它。我认为没有一个解决方案没有令人讨厌的检查和强制转换实例。+1这是他们bes的通配符t、 吹毛求疵:这些“少数古怪案例”是什么?IIRC
null
尽可能地涵盖了制作人所能消费的内容。@PaulBellora:这与“通配符捕获”有关。所以你可以做类似于
list.add(list.get(0))的事情
。上一次我检查你不能这样做,但是-在某处有一篇关于它的帖子。@PaulBellora:啊,也许你不能。TBH,我只读过关于它的文章,我从来没有在实践中需要这样做。@PaulBellora它不必使用原始类型。`void swap(List List List){swap2(List);}void swap2(List){List.set(I,List.get(j))}请参阅JLS 5.1.10中的示例,但我认为您的解决方案不会编译,因为您正在更改返回类型。编辑:nm,它之所以有效是因为协变返回类型,明白了。我选择此解决方案是因为它易于集成、工作和清除。
class Team implements Iterable<Member>
{
    public Iterator<Member> iterator() { ... }
}

for(Member member : team) ...
class Team
{
    Iterable<Member> members() { ... }
}
for(Member member : team.members()) ...
interface IA
{
    Iterable<? extends A> members();
}

interface IB extends IA
{
    @Override
    Iterable<? extends B> members();
}
public interface Iterable<T> 

    Iterator<T> iterator();
public interface Iterable<T> 

    Iterator<? extends T> iterator();