2017-07-29 107 views
4

我有以下代碼來理解協變和下限,我故意讓代碼有編譯錯誤。類型的表達式不符合期望的類型B

getOrElse工程,這是從選項[+ T]的getOrElse方法類似。

我會問爲什麼getOrElse2getOrElse3不工作,以更好地理解協變和下限。

所述的編譯錯誤被粘貼爲代碼中的註釋:

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 
    } 
} 

回答

1

1. getOrElse3[B <: A]:指型BcontrovariantAB是/的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它意味着限定亞型B的新型A(未類級別類型A)。並且由於您將x類泛型類型A返回到類型B,因此編譯器應拋出類型不匹配錯誤。

+0

我明白[B <:A]意思是B是A的子類型/下界,你的意思是[B <:A]也意味着B類型的控制變量A?我認爲上限無關協變或控制。另外,我不明白'協變類型只能啓用綁定類型A'的超類型。 – Tom

1

通過對方法getOrElse2指定[A <: B],你定義一個新的本地類型A無關的原始類型Ax屬,如@ chengpohi的答案解釋。

至於方法getOrElse3[B <: A]被逆着trait Function1的定義,要求它的參數是逆變:

trait Function1[-T1, +R] extends AnyRef { 
    abstract def apply(v1: T1): R 
    // ... 
} 

隨着協變[+ A],對於亞型A MyOption的實例S [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參數的逆變。

+0

我不明白聲明'對於協變[+ A],A的子類型B可以替換A,因此違反函數1參數的逆變要求。我現在正在腦中燃燒。 – Tom

+0

@Tom,對不起,我不清楚。我已經完善了相關聲明。 –

+0

謝謝@ leo-c,我可以理解MyOption [S](x:S)可以代替MyOption [A](x:A)的一個實例,這是協變性;另外,據我所知,getOrElse3 [S]不能代替getOrElse3 [A](getOrElse3 [A]應該能夠代替getOrElse3 [S]),因爲Fucntion1的論點是controvariance。給出這兩個事實,我仍然不明白問題出在哪裏我的getOrElse3方法的謊言,也許我需要一些代碼來幫助說明問題(例如,假設它的定義是正確的第一個) – Tom

相關問題