在Scala中避免asInstanceOf的方法

时间:2019-03-20 19:21:27

标签: scala generics scala-collections

我在Scala中具有以下特征和类层次结构:

trait A
trait B[T] extends A {
  def v: T
}
case class C(v:Int) extends B[Int]
case class D(v:String) extends B[String]
val l:List[A] = C(1) :: D("a") :: Nil
l.foreach(t => println(t.asInstanceOf[B[_]].v))

我无法更改类型层次结构或列表的类型。

是否有更好的方法来避免asInstanceOf [B [_]]语句?

3 个答案:

答案 0 :(得分:5)

您可以尝试模式匹配。

l.collect{case x :B[_] => println(x.v)}

答案 1 :(得分:4)

您可以尝试如下操作:

swagger-play2

它不需要任何for (x <- l.view; y <- Some(x).collect { case b: B[_] => b }) println(y.v) isInstanceOf,并且即使您的列表包含不是asInstanceOf的{​​{1}}也不会崩溃。它还不会创建任何冗长的列表作为中间结果,而只会创建短暂的小A


不那么简洁,但是也没有那么令人惊讶的解决方案:

B[_]

如果您可以将Option的类型更改为for (x <- l) { x match { case b: B[_] => println(b.v) case _ => /* do nothing */ } } ,这将是更可取的解决方案。

答案 2 :(得分:1)

我认为最理想的方法是为B提供一个提取器对象,并为B值提供模式匹配:

object B {
    def unapply[T](arg: B[T]): Some[T] =  Some(arg.v)
  }
l.collect{case B(x) => println(x)} 

如果在源文件中声明了B,则无法更改,而提取器对象可能需要使用其他名称。