这种协方差在 C# 中是可能的:
IEnumerable<A> a = new List<A>();
IEnumerable<B> b = new List<B>();
a = b;
...
class A {
}
class B : A {
}
这在 Java 中是不可能的:(Iterable: Seen in this question Java Arrays & Generics : Java Equivalent to C# IEnumerable<T>)。
Iterable<A> a = new ArrayList<A>();
Iterable<B> b = new ArrayList<B>();
a = b;
...
class A {
}
class B extends A {
}
使用 Iterable,Java 看不到这两个集合是协方差的
Java中哪个可迭代/可枚举接口可以促进协变?
协方差的另一个很好的例子,给定上面相同的 A 类和 B 类,这在 Java 和 C# 上都是允许的:
A[] x;
B[] y = new B[10];
x = y;
从版本 1 开始,这两种语言都具有该功能。很高兴他们正在取得进展,以使其在泛型上成为现实。尽管在语法方面,C# 的摩擦较小。
所有 OOP 语言都必须使用协变,否则 OOP 继承将是无用的练习,例如
A x;
B y = new B();
x = y;
这种权力也应该扩展到泛型。
感谢大家的回答和见解。现在有了一个具有协变能力的 Java 泛型的可重用方法。这不是我们中的一些人想要的语法,但 it( <? extends classHere>
) 确实符合要求:
import java.util.*;
public class Covariance2 {
public static void testList(Iterable<? extends A> men) {
for(A good : men) {
System.out.println("Good : " + good.name);
}
}
public static void main(String[] args) {
System.out.println("The A");
{
List<A> team = new ArrayList<A>();
{ A player = new A(); player.name = "John"; team.add(player); }
{ A player = new A(); player.name = "Paul"; team.add(player); }
testList(team);
}
System.out.println("The B");
{
List<B> bee = new ArrayList<B>();
{ B good = new B(); good.name = "George"; bee.add(good); }
{ B good = new B(); good.name = "Ringo"; bee.add(good); }
testList(bee);
}
}
}
class A { String name; }
class B extends A {}
输出:
The A
Good : John
Good : Paul
The B
Good : George
Good : Ringo
如果有人对它在 C# 中的样子感兴趣
using System.Collections.Generic;
using System.Linq;
public class Covariance2 {
internal static void TestList(IEnumerable<A> men) {
foreach(A good in men) {
System.Console.WriteLine("Good : " + good.name);
}
}
public static void Main(string[] args) {
System.Console.WriteLine("The A");
{
IList<A> team = new List<A>();
{ A player = new A(); player.name = "John"; team.Add(player); }
{ A player = new A(); player.name = "Paul"; team.Add(player); }
TestList(team);
}
System.Console.WriteLine("The A");
{
IList<B> bee = new List<B>();
{ B good = new B(); good.name = "George"; bee.Add(good); }
{ B good = new B(); good.name = "Ringo"; bee.Add(good); }
TestList(bee);
}
}
}
class A { internal string name; }
class B : A {}