簡體   English   中英

scala類型的上限和下限

[英]Upper and Lower bound on scala type

考慮以下層次結構:

class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3

我想編寫一個只接受C2C3類型的函數。 為此我想到了以下內容:

 def f [C >: C3 <: C2](c :C) = 0

我期待以下行為

f(new C1)  //doesn't compile, ok
f(new C2)  //compiles, ok
f(new C3)  //compiles, ok
f(new C4)  // !!! Compiles, and it shouldn't 

問題是用C4調用它,我不想允許,但編譯器接受。 我知道C4 <: C2是正確的, C4可以看作是C3 但是當指定綁定[C >: C3 <: C2] ,我希望編譯器找到一個同時尊重兩個邊界的C ,而不是一個接一個。

問題是:有沒有辦法實現我想要的,如果沒有,編譯器是否試圖避免與此有些不一致?

編輯 :從答案中我意識到我的推定是錯誤的。 C4總是滿足C >: C3 ,因此兩個邊界確實得到了尊重。 我的用例的方法是C3 <:< C

靜靜地,是的。 施加此約束非常簡單:

def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0

f(new C4)現在不會編譯。

問題是,在編譯時可能無法禁止以下行為:

val c: C3 = new C4
f(c)

這里變量c有靜態類型C3 ,它通過編譯器傳遞任何類型的類型檢查,但它在運行時實際上是C4

在運行時,您當然可以使用反射或多態檢查類型並拋出錯誤或返回Failure(...)None

我發現另一個stackoverflow問題的解釋非常有用:

S>:T只是意味着如果傳入的類型S等於T或其父類,則使用S。 如果您將一個子級別的類型傳遞給T,那么將使用T.

所以在你的例子中,但首先應該編譯。 以下示例說明了其含義:讓我們重新定義f:

def f[U >: C3 <: C2](c: U) = c

接着:

 val a2 = f(new C2)
 val a3 = f(new C3) 
 val a4 = f(new C4) 
 List[C2](a2, a3, a4)  //compiles
 List[C3](a3, a4)  //compiles
 List[C4](a4)  //does not cause a4 is C3

希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM