【问题标题】:Generic unapply method for different types of List不同类型列表的通用取消应用方法
【发布时间】:2013-06-03 03:54:55
【问题描述】:

有没有办法用泛型泛化这段代码?

object ListInt {
  def unapply(o: Any): Option[List[Int]] = o match {
    case lst: List[_] if(lst.forall(_.isInstanceOf[Int])) => 
      Some(lst.asInstanceOf[List[Int]])
    case _ => None
  }
}
object ListDouble {
  def unapply(o: Any): Option[List[Double]] = o match {
    case lst: List[_] if(lst.forall(_.isInstanceOf[Double])) =>
      Some(lst.asInstanceOf[List[Double]])
    case _ => None
  }
}
object ListString {
  def unapply(o: Any): Option[List[String]] = o match {
    case lst: List[_] if(lst.forall(_.isInstanceOf[String])) =>
      Some(lst.asInstanceOf[List[String]])
    case _ => None
  }
}

val o: Any = List("a", "b", "c")
o match {
  case ListInt(lst) => println(lst.sum)
  case ListDouble(lst) => println(lst.product)
  case ListString(lst) => println(lst.mkString("(", ", ", ")"))
  case _ => println("no match")
}

【问题讨论】:

标签: scala generics


【解决方案1】:
abstract class ListExtractor[A](implicit ct: reflect.ClassTag[A]) {
  def unapply(o: Any): Option[List[A]] = o match {
    case lst: List[_] if (lst.forall(ct.unapply(_).isDefined)) =>
      Some(lst.asInstanceOf[List[A]])
    case _ => None
  }
}

object ListInt    extends ListExtractor[Int   ]
object ListString extends ListExtractor[String]

val o: Any = List("a", "b", "c")
o match {
  case ListInt   (lst) => println(lst.sum)
  case ListString(lst) => println(lst.mkString("(", ", ", ")"))
  case _               => println("no match")
}

【讨论】:

    【解决方案2】:

    看来TypeTag是要走的路:

    import scala.reflect.runtime.universe._
    
    def foo[A: TypeTag](lst: A) = typeOf[A] match {
      case t if t =:= typeOf[List[Int]] => lst.asInstanceOf[List[Int]].sum
      case t if t =:= typeOf[List[Double]] => lst.asInstanceOf[List[Double]].product
      case t if t =:= typeOf[List[String]] => lst.asInstanceOf[List[String]].mkString("(", ", ", ")")
    }
    
    println(foo(List("a", "b", "c")))
    

    查看这篇优秀的帖子以获得详细的解释:

    Scala: What is a TypeTag and how do I use it?

    【讨论】:

    • 但是,List[Any](1, 2, 3) 不会以这种方式生成 List[Int]。我不知道 OP 是否要求如此?
    • 好吧,我实际上需要能够匹配 Any 类型的数据,但这两种解决方案都非常有用。
    • @0__ 感谢您指出,我想避免循环遍历列表,但似乎没有简单的方法。
    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多