如何使用模式匹配中的类型信息?

时间:2016-08-03 08:30:01

标签: scala generics reflection type-inference

我有以下设置:

trait TypeA { override def toString() = "A" }
trait TypeB { override def toString() = "B" }
trait TypeC { override def toString() = "C" }

def foo[T](t: T) = println(t)

现在我可以这样做:

val valueB: Any = new TypeB {}

val typedValue = valueB match {
  case t: TypeA => foo(t)
  case t: TypeB => foo(t)
  case t: TypeC => foo(t)
}
// prints "B"

如果我想概括这个模式匹配块,我可以简单地做:

val typedValue = valueB match {
  case t => foo(t)
}

它会起作用。但是,在我的实际用例中,我需要在调用方法时显式声明类型信息,因为没有函数参数来推断它。所以如果foo()是使用类型参数T参数化的泛型方法,但没有要推断的那个类型的实际参数,我可以将其概括为仅与一个案例语句匹配的模式(可能使用Reflection API)?

那么,如何概括呢?

val typedValue = valueB match {
  case t: TypeA => foo[TypeA]()
  case t: TypeB => foo[TypeB]()
  case t: TypeC => foo[TypeC]()
  ...
}

1 个答案:

答案 0 :(得分:1)

  

如果我想概括这个模式匹配块,我可以简单地做:

val typedValue = valueB match {
  case t => foo(t)
}

一般情况下你不能。例如。如果foo(x: TypeA)foo(x: TypeB)foo(x: TypeC)是单独的重载。这就是你的真实代码的情况:你必须为JsObject等编写单独的方法,因为那些value调用碰巧具有相同的名称;你不能写foo(x: JsValue)foo[T <: JsValue](x: T)哪个会做你想要的(没有你想要避免的相同匹配)。

如果你有一个单一的多态方法:因为通用参数被删除,如果你有def foo[T]() = ...foo[TypeA]()foo[TypeB]()foo[TypeC]()将执行相同的实际代码(这不适用于classOfisInstanceOfasInstanceOf,但这些是唯一的例外,因为它们不是真正的通用方法)。所以你可以打电话给foo[<type-of-valueB>]。为了使它们不同,foo必须有一个隐含的参数,该参数取决于T,例如

trait Baz[A] { ... }
object Baz {
  implicit val bazTypeA: Baz[TypeA] = ...
  ...
}

def foo[A]()(implicit baz: Baz[A]) = ...

在这种情况下,避免分支的方法是调用foo的方法接受相同的隐式:

def bar[A](value: A)(implicit baz: Baz[A]) = foo[A]()

bar(new TypeA) // uses bazTypeA