我有以下代码来理解协变和下界,我故意让代码编译错误。
getOrElse
有效,与选项[+ T]的getOrElse
方法类似。
我会问为什么getOrElse2
和getOrElse3
不能更好地理解协变和下限。
编译错误在代码中粘贴为注释:
class MyOption[+A](val x: A) {
def get():A = x
//similar to Option.getOrElse,which works
def getOrElse[B>:A ](default: => B): B = {
if (x != null) x else default
}
//Compiling Error: Expression of type A doesn't conform to Expected type B
def getOrElse2[B, A<:B ](default: => B): B = {
if (x != null) x else default
}
//Covariant type A occurs in controvariant position in type A of value B
def getOrElse3[B <: A](default:=>B): A = {
if (x != null) x else default
}
}
答案 0 :(得分:1)
1. getOrElse3[B <: A]
:表示类型为B
控制 A
,B
为子类型/下限 A
,协变类型 A
不允许这样做,因为协变类型仅启用超类型绑定对于A
类型。而且这等于:
//Error:covariant type A occurs in contravariant position in type A of value default
def getOrElse3(default: A): A = {
if (x != null) x else default
}
为什么选项类型协方差?这是用于将A
绑定到超类型A ,如Some(1)
可以由接受参数的方法Option[AnyVal]
使用。
2. def getOrElse2[B, A<:B ]
:A<:B
这意味着定义子类型A
的新类型B
(不是类级别类型A
)。并且由于您将类通用类型x
的{{1}}返回到类型A
,编译器应该抛出类型不匹配错误。
答案 1 :(得分:1)
通过为方法[A <: B]
指定getOrElse2
,您需要定义与A
所属的原始类型A
无关的新本地类型x
如@ chengpohi的回答中所述。
对于方法getOrElse3
,[B <: A]
违反trait Function1的定义,要求其参数为逆变:
trait Function1[-T1, +R] extends AnyRef {
abstract def apply(v1: T1): R
// ...
}
对于协变量[+ A],对于S
的子类型A
,MyOption [S](x:S)的实例可以替换MyOption [A]的实例(x:A) );但由于Function1
参数的逆变要求,getOrElse3 [S]无法替换getOrElse3 [A]。出于同样的原因,以下方法也会使编译器失败:
// Compiling Error: covariant type A occurs in contravariant position in type A of value default
def printDefault(default: A): Unit = {
println(default)
}
要保留您的协变[+ A],将A
设置为与您的第一个getOrElse
方法相同的下限,可以避免冲突Function1
参数的逆转。