我可以在Scala匹配语句中使用类变量吗?

Dan*_*ell 2 scala class

说我有这样的事情:

obj match {
    case objTypeOne : TypeOne => Some(objTypeOne)
    case objTypeTwo : TypeTwo => Some(objTypeTwo)
    case _ => None
}
Run Code Online (Sandbox Code Playgroud)

现在我想概括一下,传入其中一种类型来匹配:

obj match {
    case objTypeOne : clazz => Some(objTypeOne)
    case objTypeTwo : TypeTwo => Some(objTypeTwo)
    case _ => None
}
Run Code Online (Sandbox Code Playgroud)

但这是不允许的,我认为是出于句法而非语义的原因(虽然我猜也是即使clazz是一个Class [C],类型也会被删除,因此选项的类型将会丢失).

我结束了:

if(clazzOne.isAssignableFrom(obj.getClass)) Some(clazz.cast(obj))
if(obj.isInstanceOf[TypeTwo]) Some(obj.asInstanceOf[TypeTwo])
None
Run Code Online (Sandbox Code Playgroud)

我只是想知道是否有更好的方式.

mkn*_*ssl 11

您可以定义一个与您的对象匹配的提取器:

class IsClass[T: Manifest] {
  def unapply(any: Any): Option[T] = {
    if (implicitly[Manifest[T]].erasure.isInstance(any)) {
       Some(any.asInstanceOf[T])
    } else {
       None
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

所以让我们测试一下:

class Base { def baseMethod = () }
class Derived extends Base

val IsBase = new IsClass[Base]

def test(a:Any) = a match {
    case IsBase(b) => 
      println("base")
      b.baseMethod
    case _ => println("?")
  }

test(new Base)
test(1)
Run Code Online (Sandbox Code Playgroud)

例如,您必须为提取器定义val,不能内联IsBase.否则它将被解释为提取器.


axe*_*l22 5

您可以使用模式保护来实现这一目标.尝试这样的事情:

obj match {
    case objTypeTwo : TypeTwo => Some(objTypeTwo)
    case objTypeOne if clazz.isAssignableFrom(objTypeOne.getClass) => Some(clazz.cast(objTypeOne))
    case _ => None
}
Run Code Online (Sandbox Code Playgroud)