假设:
sealed trait Request
sealed trait HasProxy extends Request
sealed trait HasFoo extends Request
case object One extends HasProxy with HasFoo
case object Two extends HasFoo
case object Three extends HasProxy with HasFoo
case object Four extends HasFoo
case object Five extends HasProxy
我定义了一个接受HasFoo
类型的函数。
def f(x: HasFoo) = ???
最后,我尝试编写一个函数,给定Request
,HasFoo
个案例的模式匹配,即One
,Two
,{{1} }和Three
。
Four
然而,上述失败。
他们每个人都有scala> def foo(request: Request) = request match {
| case xxx @ (One | Two | Three | Four ) => f(xxx)
| }
<console>:23: error: type mismatch;
found : Request
required: HasFoo
case xxx @ (One | Two | Three | Four ) => f(xxx)
^
个共同点,但我不确定这是如何适用于模式匹配的。
HasFoo
而不是为scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> lub ( List( typeOf[One.type], typeOf[Two.type],
| typeOf[Three.type], typeOf[Four.type] )
| )
res2: reflect.runtime.universe.Type = HasFoo with Serializable with Product
f(_)
One ... Four
或检查运行时类型,即scala> def foo(request: Request) = request match {
| case One => ???
| case Two => ???
| ...
| case _ => ???
| }
foo: (request: Request)Nothing
:
case xxx : One | Two | Three | Four
我有更好的选择吗?
答案 0 :(得分:4)
这可能是编译器类型推断中的一个错误或至少是一个不受欢迎的限制,但一般来说,如果编译器无法理解某些东西的实际类型是什么 - 在这里你可以确定 - 你可以只是到正确的类型:
case xxx @ (One | Two | Three | Four ) => f(xxx.asInstanceOf[HasFoo])
是的,如果它在将来被修改,它就会变得不优雅并且可能不安全,但你可以通过评论几乎完全解决这个问题。
如果您希望编译器确保强制转换,那么模式匹配并使用guard子句拒绝任何不符合您要求的内容,例如:
case xxx: HasFoo
if (xxx match { case One | Two | Three | Four => true
case _ => false
}) => f(xxx)
答案 1 :(得分:1)
如果你想匹配HasFoo
的任何内容,那么显而易见:
def foo(request: Request) = request match {
case xxx: HasFoo => f(xxx)
case _ => ???
}
由于One
,Two
,Three
和Four
都延伸HasFoo
,所以第一种情况将匹配所有四种类型;但不是Five
。