【问题标题】:Scala pattern match on classes with a typed parameter具有类型参数的类上的 Scala 模式匹配
【发布时间】:2016-04-02 15:11:29
【问题描述】:

我正在尝试对带有类型参数的自定义类进行模式匹配:

class Foo[A]

def isMyFoo[A: ClassTag](v: Any) = v match {
    case mine: Foo[A] => "my foo"
    case other: Foo[_] => "not my foo"
    case _ => "not a foo"
}

那行不通;不管Foo是什么类型,我都会得到"my foo"

我能够做出这样的事情的唯一方法是:

class Foo[A](implicit t: ClassTag[A]) {
    val tag = t
}

def isMyFoo[A: ClassTag](v: Any) = v match {
    case foo: Foo[_] =>
        if (foo.tag == classTag[A]) "my foo"
        else "not my foo"
    case _ => "not a foo"
}

有没有更优雅的方法呢?我必须将ClassTag 保留在Foo 中吗?

【问题讨论】:

    标签: scala generics reflection


    【解决方案1】:

    我必须将 ClassTag 保留在 Foo 中吗?

    是的。 Foo 的类型参数在运行时被擦除,所以你只知道你有一个Foo[_]。解决这个问题的唯一方法是使用ClassTagTypeTag 保存类型信息。如果你打算走这条路,我建议使用TypeTag,因为你将能够使用更精细的类型。 ClassTags 仍然只能进行模类型擦除。

    例如,使用ClassTag,这是错误的:

    scala> val fooListString = new Foo[List[String]]
    fooListString: Foo[List[String]] = Foo@f202d6d
    
    scala> isMyFoo[List[Int]](fooListString)
    res4: String = my foo
    

    但以下方法会起作用:

    class Foo[A](implicit t: TypeTag[A]) {
        val tag = t
    }
    
    def isMyFoo[A: TypeTag](v: Any) = v match {
        case foo: Foo[_] =>
            if (foo.tag.tpe =:= typeOf[A]) "my foo"
            else "not my foo"
        case _ => "not a foo"
    }
    
    scala> val fooListString = new Foo[List[String]]
    fooListString: Foo[List[String]] = Foo@6af310c7
    
    scala> isMyFoo[List[Int]](fooListString)
    res5: String = not my foo
    

    【讨论】:

      猜你喜欢
      • 2016-05-12
      • 2020-08-23
      • 2014-07-01
      • 2015-02-28
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      相关资源
      最近更新 更多