【问题标题】:Scala Pattern Matching on Generic Traits通用特征上的 Scala 模式匹配
【发布时间】:2016-10-25 21:43:34
【问题描述】:

我有一个这样定义的特征:

sealed trait MyTrait[+A] {
  def name: String
  def id: Long
  def someType: A 
}

我现在有一些案例类扩展了这个特性,如下所示:

object MyTrait {
  case class One[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A]

  case class Two[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A]

  case class Three[+A](name: String, id: Long, someType: A) extends MyTrait[A]
}

现在,我有一个可能包含这些案例类之一的列表,我必须从给定的列表中收集各个案例类,并使用 instanceOf 检查如下:

val myBigList = List(One[SomeType], Two[SomeType], Three[SomeType], One[SomeType])

val allOnes = myBigList.collect {
  case elem if elem.isInstanceOf[One[_]] => elem.asInstanceOf[One]]
}

val allTwos = myBigList.collect {
  case elem if elem.isInstanceOf[Two[_]] => elem.asInstanceOf[Two]]
}

val allThrees = myBigList.collect {
  case elem if elem.isInstanceOf[Three[_]] => elem.asInstanceOf[Three]]
}

有没有更好的方法?我的意思是有没有办法避免 isInstanceOf 和 asInstanceOf?

【问题讨论】:

    标签: scala


    【解决方案1】:

    如果您想将One[String]One[Int] 放在一个桶中,这很好,这意味着如果您不关心内部类型。

    但您可以使用foldLeft 一次性完成此操作,而不是三遍。

    def bucketize(list: List[MyTrait[_]]): (List[One[_]], List[Two[_]], List[Three[_]]) = {
      list.foldLeft(((List.empty[One[_]], List.empty[Two[_]], List.empty[Three[_]]))){ (r, c) => 
        val ((one, two, three)) = r
        c match { 
          case x: One[_] => ((one ++ List(x), two, three))
          case x: Two[_] => ((one, two ++ List(x), three))
          case x: Three[_] => ((one, two, three ++ List(x)))
        }
       }
    }
    

    你得到三组列表,第一个列表是 List[One],第二个是 List[Two],依此类推...

    用法:

    val ((one, two, three))  = bucketize(list)
    

    【讨论】:

    • 单程如何?我需要外面的个人价值观!
    • @sparkr ... 用示例编辑了答案。请看一下
    猜你喜欢
    • 2016-10-13
    • 2015-03-22
    • 2014-01-03
    • 1970-01-01
    • 2011-11-27
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多