方法重载参数化类型

时间:2014-04-01 18:45:43

标签: scala

只是想知道是否有办法使用参数化类型调用重载方法。例如,定义以下对象:

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?

3 个答案:

答案 0 :(得分:3)

两种方法:

第一种方式假设XY是已知类型而非泛型类型。然后你可以做以下事情:

 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 
}