[英]Upper and Lower bound on scala type
考慮以下層次結構:
class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3
我想編寫一個只接受C2
和C3
類型的函數。 為此我想到了以下內容:
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.