函数上的Scala模式匹配';s第一类型参数
假设您在Scala中有这样的方法定义:函数上的Scala模式匹配';s第一类型参数,scala,pattern-matching,type-erasure,type-parameter,Scala,Pattern Matching,Type Erasure,Type Parameter,假设您在Scala中有这样的方法定义: def handle[T](fn: T => Unit): Unit 是否可以根据功能参数T的类型进行模式匹配,以根据T的类型调用不同的方法 您是否需要重新编写它,改为使用Function1,然后对其进行模式匹配 我尝试了以下操作,但由于类型擦除而无法工作: class A { def x(fn: A => Unit): Unit = fn(this) } class B { def y(fn: B => Unit): Uni
def handle[T](fn: T => Unit): Unit
是否可以根据功能参数T的类型进行模式匹配,以根据T的类型调用不同的方法
您是否需要重新编写它,改为使用Function1
,然后对其进行模式匹配
我尝试了以下操作,但由于类型擦除而无法工作:
class A {
def x(fn: A => Unit): Unit = fn(this)
}
class B {
def y(fn: B => Unit): Unit = fn(this)
}
def handle[T](fn: Function1[T, Unit]): Unit = {
fn match {
case fnA: Function1[A, Unit] =>
new A().x(fnA)
case fnB: Function1[B, Unit] =>
new B().y(fnB)
}
}
可能是抽象类型?我想我用TypeTag
实例找到了答案:
import scala.reflect.runtime.universe._
class A {
def x(fn: A => Unit): Unit = fn(this)
override def toString = "A"
}
class B {
def y(fn: B => Unit): Unit = fn(this)
override def toString = "B"
}
def handle[T : TypeTag](fn: Function1[T, Unit]): Unit = typeOf[T] match {
case t if t =:= typeOf[A] => new A().x(fn.asInstanceOf[Function1[A, Unit]])
case t if t =:= typeOf[B] => new B().y(fn.asInstanceOf[Function1[B, Unit]])
}
handle[A] { a: A =>
println("It's " + a)
}
handle[B] { b: B =>
println("It's " + b)
}
它将打印预期的输出:
It's A
It's B
如果有人有更好的解决方案,请告诉我:)您可以使用typeclass执行此操作,那么不需要反射或类型标记:
// Typeclass defines things that can be handled
trait Handleable[T] {
def handle(fn: T => Unit)
}
// Two typeclass instances, one for A and one for B
implicit object AHandleable extends Handleable[A] {
def handle(fn: A => Unit) = new A().x(fn)
}
implicit object BHandleable extends Handleable[B] {
def handle(fn: B => Unit) = new B().y(fn)
}
// implicitly grab the instance for whichever type we are using (A, B...)
def handle[T](f: T => Unit)(implicit h: Handleable[T]) = h.handle(f)
//or equivalently:
//def handle[T: Handleable](f: T => Unit) = implicitly[Handleable[T]].handle(f)
handle((a: A) => println(a)) //> A
handle((b: B) => println(b)) //> B
由于A和B没有有用的公共超类(我假设你不能简单地给它们一个!),typeclass模式允许我们在不修改原始类的情况下“附加”公共超特性(“特殊多态性”)
我们以后可以通过添加更多的typeclass实例来支持附加的案例(对于C、D等),而无需修改handle()
方法。是否可以更改handle
的签名?改变A
和B
?看起来很整洁,我认为它的性能比反射更好。谢谢