【问题标题】:Scala generic type matchingScala 泛型类型匹配
【发布时间】:2014-12-11 19:36:41
【问题描述】:

我发现自己经常做这样的模式匹配

val foo: Foo = ...
foo match {
  case bar: Bar => Some(bar)
  case _ => None
}

我想让这个更短。

val foo: Foo = ...
optInstance[Foo, Bar](foo)

可能性 1 - 直接翻译

def optInstance[A, B <: A](a: A) = a match {
  case b: B => Some(b)
  case _ => None
}
// warning: abstract type pattern B is unchecked since it is eliminated by erasure

可能性 2 - try-catch

def optInstance[A, B <: A](a: A) =
  try {
    Some(a.asInstanceOf[B])
  } catch {
    case e: ClassCastException => None
  }
// no warnings

可能性 3 - if-else

def optInstance[A, B <: A](a: A) =
  if(a.isInstanceOf[B]) {
    Some(a.asInstanceOf[B])
  } else {
    None
  }
// no warnings

它们都不起作用。 (斯卡拉 2.11.2)


有没有通用的写法

foo match {
  case bar: Bar => Some(bar)
  case _ => None
}

(如果没有,至少有更短的方法吗?)

【问题讨论】:

  • 当 foo 不是 Bar 时,它是什么?

标签: scala generics casting


【解决方案1】:

只需为您的第一个实现添加一个隐式 ClassTag

import scala.reflect.ClassTag

def optInstance[A, B <: A : ClassTag](a: A): Option[B] = a match {
  case b: B => Some(b)
  case _ => None
}

例子:

sealed trait Foo
case object Bar extends Foo
case object Baz extends Foo

scala> optInstance[Foo, Bar.type](Bar)
res4: Option[Bar.type] = Some(Bar)

scala> optInstance[Foo, Bar.type](Baz)
res5: Option[Bar.type] = None

【讨论】:

  • 这是否仍然适用于不仅仅是“类”的类型......比如特征?
【解决方案2】:

使用隐式值类的更简洁的方式:

 implicit class AsOpt[A](val a: A) extends AnyVal {
   def asOpt[B <: A : scala.reflect.ClassTag]: Option[B] = a match {
     case b: B => Some(b)
     case _    => None
   }
 }

例子:

 val seq: Seq[Int] = Seq.empty
 seq.asOpt[List[Int]]   // Option[List[Int]] = Some(List())
 seq.asOpt[Vector[Int]] // Option[Vector[Int]] = None

【讨论】:

  • 爱它。在我发现ClassTag 之后,我本来打算这样做。并充分利用价值类。
【解决方案3】:

如果没有通用函数,您可以使用Optioncollect

class Foo
class Bar extends Foo
class Baz extends Foo

scala> val foo: Foo = new Bar
scala> Some(foo).collect { case b: Bar => b }
res1: Option[Bar] = Some(Bar@483edb6b)

scala> val baz: Foo = new Baz
scala> Some(baz).collect { case b: Bar => b }
res3: Option[Bar] = None

【讨论】:

    猜你喜欢
    • 2013-12-21
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2013-07-06
    • 2014-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    相关资源
    最近更新 更多