我不認爲,開箱即可,以令人滿意的方式強制執行。例如,一種可能的解決方案可能是:
scala> def test[X <: Outer#Inner](a: X)(b: X) =()
test: [X <: Outer#Inner](a: X)(b: X)Unit
scala> test(o1.Inner())(o1.Inner())
scala> test(o1.Inner())(o2.Inner())
<console>:16: error: type mismatch;
found : o2.Inner
required: o1.Inner
test(o1.Inner())(o2.Inner())
^
看起來不錯,但您可以通過顯式傳入類型參數來繞過它。 (同樣的方式去爲@ OlivierBlanvillain的解決方案)
scala> test[Outer#Inner](o1.Inner())(o2.Inner())
現在,讓我們嘗試以下操作:
scala> def test[X <: Outer](a: X#Inner)(b: X#Inner) =()
test: [X <: Outer](a: X#Inner)(b: X#Inner)Unit
scala> test(o1.Inner())(o2.Inner())
不行的,scalac推斷X
是Outer
,這是不夠具體,無論如何,我們可以提供Outer
作爲顯式類型參數。我們需要一種強制X
爲單身類型的方法,以便它只能表示路徑o1
或o2
,而不是某種可以由無限多的值居住的一般類型。有是的一種方法。斯卡拉爲此具有標記特徵Singleton
。我們來試試吧:
scala> def test[X <: Outer with Singleton](a: X#Inner)(b: X#Inner) =()
test: [X <: Outer with Singleton](a: X#Inner)(b: X#Inner)Unit
scala> test(o1.Inner())(o1.Inner())
<console>:15: error: inferred type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton]
test(o1.Inner())(o1.Inner())
^
<console>:15: error: type mismatch;
found : o1.Inner
required: X#Inner
test(o1.Inner())(o1.Inner())
^
現在我們的有效案例不再適用了!問題是scalac拒絕推斷單身人士類型。我們必須通過他們明確:
scala> test[o1.type](o1.Inner())(o1.Inner())
無效的情況下不工作了:
scala> test(o1.Inner())(o2.Inner())
<console>:16: error: inferred type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton]
test(o1.Inner())(o2.Inner())
^
<console>:16: error: type mismatch;
found : o1.Inner
required: X#Inner
test(o1.Inner())(o2.Inner())
^
scala> test[o1.type](o1.Inner())(o2.Inner())
<console>:16: error: type mismatch;
found : o2.Inner
required: o1.Inner
test[o1.type](o1.Inner())(o2.Inner())
^
scala> test[Outer](o1.Inner())(o2.Inner())
<console>:17: error: type arguments [Outer] do not conform to method test's type parameter bounds [X <: Outer with Singleton]
test[Outer](o1.Inner())(o2.Inner())
^
所以這個強制執行我們想要的規則,但你必須在類型傳遞明確.. 。
編輯
其實原來你可以執行此操作時不會丟失類型推斷,也不需要任何外部庫的幫助,但您可能不會喜歡它:-p
META EDIT如評論中指出的那樣,如果您嘗試足夠努力,仍然可以繞過,所以我想你是堅持以上解決方案。
scala> import scala.language.existentials
import scala.language.existentials
scala> def test[X <: x.Inner forSome { val x: Outer }](a: X, b: X) =()
test: [X <: x.Inner forSome { val x: Outer }](a: X, b: X)Unit
scala> test(o1.Inner(), o1.Inner())
scala> test(o1.Inner(), o2.Inner())
<console>:16: error: inferred type arguments [Outer#Inner] do not conform to method test's type parameter bounds [X <: x.Inner forSome { val x: Outer }]
test(o1.Inner(), o2.Inner())
^
<console>:16: error: type mismatch;
found : o1.Inner
required: X
test(o1.Inner(), o2.Inner())
^
<console>:16: error: type mismatch;
found : o2.Inner
required: X
test(o1.Inner(), o2.Inner())
^
scala> test[o1.Inner](o1.Inner(), o2.Inner())
<console>:16: error: type mismatch;
found : o2.Inner
required: o1.Inner
test[o1.Inner](o1.Inner(), o2.Inner())
^
不錯的工作! :-) – OlivierBlanvillain
好乞丐不能選擇器:)你仍然可以通過編寫例如'test [x.Inner forSome {val x:Outer}](o1.Inner(),o2.Inner())''但它總比沒有好。 –
當然是哦。<我想我應該想到... –