我不认为,开箱即可,以令人满意的方式强制执行。例如,一种可能的解决方案可能是:
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())''但它总比没有好。 –
当然是哦。<我想我应该想到... –