只是想知道是否有办法使用参数化类型调用重载方法。例如,定义以下对象:
object Wrap {
def f(x: X) = println("x called")
def f(y: Y) = println("y called")
def f(a: Any) = println("Any")
def fp[T](t: T) = f(t)
}
当我测试时,进行以下调用
Wrap.fp(new X())
它转到对Any的调用。有没有办法可以使它从fp()调用适当的f?
答案 0 :(得分:3)
两种方法:
第一种方式假设X
和Y
是已知类型而非泛型类型。然后你可以做以下事情:
def fp: PartialFunction[Any,Unit] ={
case x: X => println("got x")
case y: Y => println("got y")
case _ => println("Any")
}
并且无需做很多旋转术就能很好地工作。
第二种方法,使用类型类:
def fp[T](t: T)(implicit f: Caller[T]) = f(t)
那就是说,你的类型类可能看起来像:
trait Caller[T]{
def apply(t: T)
}
其中您将实际内容放在范围内并使用解析顺序查找最终Caller[Any]
,以便其他每个都优先。所以我会这样做:
object Wrap{
implicit val xCal = new Caller[X]{
def apply(x: X){ println("x called") }
}
implicit val yCal = new Caller[Y]{
def apply(x: Y){ println("y called") }
}
}
object `package`{
implicit val anyCal = new Caller[Any]{
def apply(t: Any){ println("any") }
}
}
答案 1 :(得分:3)
使用类标记进行辅助匹配:
scala> class W[A: ClassTag] { def f(x: X) = 1; def f(y: Y) = 2; def f(a: A) = 3;
| def g(x: Any) = x match {
| case v: X => f(v); case v: Y => f(v); case v: A => f(v); case _ => -1 } }
defined class W
scala> trait Z
defined trait Z
scala> val w = new W[Z]
w: W[Z] = W@1685b453
scala> w g new X {}
res6: Int = 1
scala> w g new Y {}
res7: Int = 2
scala> w g new Z {}
res8: Int = 3
scala> w g "hi"
res9: Int = -1
在真正的API中,g
将采用类型参数,该参数是各种参数的一些超类型,因为没有人编写采用Any
的API。 OP中的T
参数基本上是Any
,因为它不受约束。
在我编辑时,我们忘记提到重载是邪恶的。
答案 2 :(得分:1)
def process[A](a: A) = a match {
case c: X => Wrap f c
case d: Y => Wrap f d
case _ => Wrap f a
}