所以我对功能子类型感到困惑。我有下面的内容,我正在搞乱。我知道,对于逆变,A-> Int是B-> Int的子类型,这就是为什么我能够将AToInt分配给" testBContra"。
但我认为我能做的就是将A对象传递给" testBContra" ...
testBContra(a)中
哪个不起作用。我误解了可传递的内容吗?我以为我现在可以传递一个A对象并让它返回一个Int。
class S(x: Int) {
val sInput = x
}
class A(x: Int) extends S(x){
val aInput = x
}
class B(x: Int) extends A(x){
val bInput = x
}
def AToInt(h: A): Int = h.aInput
// Checking contravariance
// val testSContra: S=>Int = AtoInt
val testAContra: A=>Int = AToInt
val testBContra: B=>Int = AToInt
val a = new A(2)
val b = new B(5)
val s = new S(10)
testAContra(b)
testBContra(b)
答案 0 :(得分:2)
testBContra
的类型为B => Int
,但由于A
不是B
的子类型,因此您无法评估testBContra(a)
。当您将函数A => Int
分配给类型为B => Int
的值时,会使用函数类型的逆变量
val testBContra: B => Int = AToInt
Function1 trait在其参数类型中是逆变的,在其结果类型中是协变的。逆变量意味着如果A
是B
的超类型,则函数A => T
是某个结果类型B => T
的函数T
的子类型。逆变性反转超/子类型关系的方向。这意味着如果你有一个功能:
def foo(f: B => Int)
您可以使用AtoInt
直接调用它,因为A => Int
是B => Int
的子类型,即
foo(AToInt)
没有函数参数的逆变,你必须将AToInt
包装在参数类型为B
的函数中,即
foo((b: B) => AToInt(b))
函数返回类型的协方差意味着如果B
是A
的子类型,则函数T => B
是某些输入类型{{1}的T => A
子类型}}。在您的示例中,由于T
是Int
和AnyVal
的子类型,Any
是AToInt
和A => AnyVal
的子类型。所以,如果你有一个功能
A => Any
然后你可以拨打def bar(f: A => AnyVal) = f(new A())
。
可以合并两种方差,例如bar(AToInt)
也是AToInt
的子类型,因为B => AnyVal
是A
和{{1}的超类型}是B
的子类型。