如何使用模式匹配的类型信息?
How to use type information from pattern matching?
我有以下设置:
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)
}
它会起作用的。但是,在我的实际用例中,我需要在调用方法时显式声明类型信息,因为没有函数参数可以从中推断出来。所以 if foo()
是一个用类型参数 T
参数化的泛型方法,但没有该类型的实际参数来推断,我可以将其概括为仅用一个 case 语句匹配的模式吗(可能使用反射API)?
那么,如何概括这个?
val typedValue = valueB match {
case t: TypeA => foo[TypeA]()
case t: TypeB => foo[TypeB]()
case t: TypeC => foo[TypeC]()
...
}
If I want to generalize this pattern matching block, I can simply do:
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]()
将执行相同的实际代码(这不适用于 classOf
、isInstanceOf
或 asInstanceOf
,但这些是唯一的例外,因为它们不是真正的通用方法)。所以你可以调用 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
我有以下设置:
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)
}
它会起作用的。但是,在我的实际用例中,我需要在调用方法时显式声明类型信息,因为没有函数参数可以从中推断出来。所以 if foo()
是一个用类型参数 T
参数化的泛型方法,但没有该类型的实际参数来推断,我可以将其概括为仅用一个 case 语句匹配的模式吗(可能使用反射API)?
那么,如何概括这个?
val typedValue = valueB match {
case t: TypeA => foo[TypeA]()
case t: TypeB => foo[TypeB]()
case t: TypeC => foo[TypeC]()
...
}
If I want to generalize this pattern matching block, I can simply do:
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]()
将执行相同的实际代码(这不适用于 classOf
、isInstanceOf
或 asInstanceOf
,但这些是唯一的例外,因为它们不是真正的通用方法)。所以你可以调用 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