我正在通过Martin Odersky的Scala-by-example(2014)阅读。 在页61上,表示从String类型到Int类型的函数被表示 作为特征Function1 [String,Int]的实例。其中Function1定义为:
trait Function1[-A,+B] {def apply(x: A): B}
还有进一步的说法
S => T是S'=> T'的子类型,条件是S'是S的子类型,T是T'的子类型。
他使用以下代码示例:
val f: (AnyRef => Int) = x => x.hashCode()
val g: (String => Int) = f
g("abc")
所以这是我的问题。 由于String是AnyRef的子类型,我假设在此示例中f表示g的子类型。那是对的吗? 如果是这样,请解释该决定中的逻辑。
答案 0 :(得分:3)
如果V
是U
的子类型,则V
可以位于U
可以的任何位置。
如果您有AnyRef => Int
,可以在任何时候使用String => Int
吗?是! String
是AnyRef
,因此您可以将其传入。
因此,AnyRef => Int
是String => Int
的子类型。这种关系(从正常情况下是“向后”)通过说函数在其参数中是逆变来描述。
那说实例 f
和g
不一定有任何关系。但他们的类型确实如此。
答案 1 :(得分:0)
f和g函数,函数具有类型方差,允许类型参数的子类型和超类型:http://docs.scala-lang.org/tutorials/tour/variances.html
在scala终端中运行以下代码将为您提供与运行示例相同的结果。
g被声明为类型(AnyRef => Int)的函数,它将函数实现为:
val f = new Function[AnyRef /*or any supertype*/,Int /*or any subType type*/] {
def apply(x: AnyRef): Int = x.hashCode()
}
它被定义为一个函数,它接受AnyRef
类型的参数,返回Int
。
g定义为接收String
并返回Int
的函数。它设置为等于f,因此它变为:
val g = new Function[String /*Supertype of AnyRef*/, Int] {
def apply(x: String): Int = x.hashCode()
}
虽然在这种情况下g不是新功能。 g只是f的另一个参考。基本上,g被强制转换为Function[String, Int]
。
编辑:由于AnyVal是Int的子类型,您也可以这样做:
val gg: (String => AnyVal) = f