Reputation: 5270
Just wondering if there is a way to call an overloaded method using a parameterized type. For example define the following object:
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)
}
When I test this making the following call
Wrap.fp(new X())
it goes to the call to the Any. Is there a way I can work it such that the appropriate f is called from fp()?
Upvotes: 4
Views: 112
Reputation: 39577
Use a class tag for assisted matching:
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
In a real API, g
would take a type parameter that is some supertype of the various params, because nobody writes API that takes Any
. The T
param in the OP is basically Any
, since it is unconstrained.
While I'm editing, we forgot to mention that overloading is evil.
Upvotes: 3
Reputation: 5023
def process[A](a: A) = a match {
case c: X => Wrap f c
case d: Y => Wrap f d
case _ => Wrap f a
}
Upvotes: 1
Reputation: 35970
Two ways to do it:
First way assumes that X
and Y
are known types and not generic types. Then you could just do the following:
def fp: PartialFunction[Any,Unit] ={
case x: X => println("got x")
case y: Y => println("got y")
case _ => println("Any")
}
and it would work very well without having to do much gymanistics.
Second way, use a type class:
def fp[T](t: T)(implicit f: Caller[T]) = f(t)
That said, your type class will probably want to look like:
trait Caller[T]{
def apply(t: T)
}
wherein you place the actual things in scope and use the order of resolution to find the final Caller[Any]
so that every else takes precedence. So I'd have it be done like this:
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") }
}
}
Upvotes: 3