協方差和逆變像數的算術跡象,當你窩在一個又一個與方差的位置,組成不同。
比較:
1] +(+a) = +a
2] -(+a) = -a
3] +(-a) = -a
4] -(-a) = +a
和
trait +[+A] { def make(): A } // Produces an A
trait -[-A] { def break(a: A) } // Consumes an A
1]
// Produces an A after one indirection: x.makeMake().make()
trait ++[+A] { def makeMake(): +[A] }
+[+[A]] = +[A]
2]
// Consumes an A through one indirection: x.breakMake(new +[A] { override def make() = a })
trait -+[-A] { def breakMake(m: +[A]) }
-[+[A]] = -[A]
3]
// Consumes an A after one indirection: x.makeBreak().break(a)
trait +-[-A] { def makeBreak(): -[A] }
+[-[A]] = -[A]
4]
// Produces an A through one indirection
// Slightly harder to see than the others
// x.breakBreak(new -[A] { override def break(a: A) = {
// you have access to an A here, so it's like it produced an A for you
// }})
trait --[+A] { def breakBreak(b: -[A]) }
-[-[A]] = +[A]
所以,當你有
def method(iter: Iterator[A])
方法的參數作爲一個整體處於逆變位置,A
處於Iterator
內部的協變位置,但是-[+[A]] = -[A]
,所以A
實際上是在這個簽名裏面的一個逆變位置,並且類需要說-A
。這是有道理的,外部用戶傳遞了一堆A
,所以它應該是逆變的。
同樣,在
def method(comp: Comparator[A])
整個方法的參數是在逆變位置,A
是在Comparator
內的逆變位置,讓您撰寫他們-[-[A]] = +[A]
,你看到A
真是一個協變位置。這也是有道理的。當您將A
傳遞到Comparator
時,外部用戶可以控制它的功能,因此有點像將A
返回給它們。
如果一個參數在共同和逆變位置,那麼它必須是不變的。這最終適用於你的兩個例子 - 它們都是不變的。 – Dima
我知道如果協變和逆變都應該是不變的。我的例子最後是兩個不同的例子。 –
'比較器'只在參數位置使用'A'。這就是說,我討厭用「技巧」來理解這個問題。 – Alec