Java lesson on generics引导我variance概念。这让我有些头疼,因为我无法找到它的简单演示。
我已经阅读了几个similar questions on stackoverflow,但我发现它们对Java学习者来说太难理解了。实际上问题在于对泛型的解释需要理解方差,并且证明了方差的概念在很大程度上依赖于泛型理解。
这个标题让我想起了学习广义相对论的日子。 - C.R. 2013年12月22日7:34
四个理论问题对我来说非常困惑,我找不到好的和简单的解释。在这里,他们是我目前的部分理解(我担心专家会非常有乐趣阅读这篇文章)。
欢迎您提供纠正和澄清的帮助(请记住,这适用于初学者,而非专家)。
答案 0 :(得分:4)
这不是特定于OO,而是与某些类型的属性有关。
例如,使用函数类型
A -> B // functional notation
public B meth(A arg) // how this looks in Java
我们有以下内容:
设C为A的子类型,D为B的子类型。以下是有效的:
B b = meth(new C()); // B >= B, C < A
Object o = meth(new C()); // Object > B, C < A
但下面的内容无效:
D d = meth(new A()); // because D < B
B b = meth(new Object()); // because Object > A
因此,要检查甲基化的调用是否有效,我们必须检查
这一点众所周知且直观。按照惯例,我们说函数的返回类型是协变,方法的参数类型是逆变。
使用参数化类型(如List),我们知道参数类型在Java等语言中是不变的,我们在这些语言中具有可变性。我们不能说C的列表是A的列表,因为如果它是这样的话,我们可以在C列表中存储A,这对于调用者来说是令人惊讶的,他们假设列表中只有Cs。但是,在值不可变的语言中,如Haskell,这不是问题。因为我们传递给函数的数据不能被改变,所以如果C 是A的子类型,则实际的列表是的列表。(注意,Haskell没有真正的subtyping,而是相关的“更多/更少多态”类型的概念。)