Reputation: 11666
I'm trying to get the classOf[the-abstract-class-Option]
, but instead I always get the classOf[the-Option-*object*]
. How can I get the class of the abstract class instead?
Both Option.getClass
and classOf[Option[_]]
gives me class scala.Option$
.
Edit: I needn't have asked this; all of a sudden, classOf[Option[_]]
works fine, weird. /Edit
Background:
I'm trying to invoke via reflection a method that takes an Option[String]
parameter.
It signature look like so: ...(..., anySectionId: Option[String], ...)...
Before I can invoke the method, I look it up via getDeclaredMethod
. But to do that, I need a list of parameter types, which I construct by calling _.getClass
on each argument I'm going to give to the method. But _.getClass
returns classOf[None]
or classOf[Some]
for Option instances, which makes getDeclaredMethod
fail, because (?) the signature is based on Option not Some/None.
Here's the code:
val clazz: Class[_] = Play.current.classloader.loadClass(className)
val paramTypes = arguments.map(_ match {
case None => Option.getClass // gives me the object, not the abstract class
case _: Some[_] => classOf[Option[_]] // this also gives me the object :-(
case x => x.getClass // results in None or Some for Option instances
})
val m: jl.reflect.Method = clazz.getDeclaredMethod("apply", paramTypes: _*)
and the last line above fails for a method with any Option
parameter (otherwise everything works fine).
Upvotes: 0
Views: 593
Reputation: 39577
The best way is use Scala reflection.
The next best way is not to make work for yourself by trying to match the param types.
Using getClass
fails for subtypes:
scala> class Foo
defined class Foo
scala> class Bar extends Foo
defined class Bar
scala> class Baz { def baz(f: Foo) = 1 }
defined class Baz
scala> val b = new Baz
b: Baz = Baz@d33eaa9
scala> val p = new Bar
p: Bar = Bar@406c5ca2
scala> classOf[Baz].getDeclaredMethod("baz", p.getClass)
java.lang.NoSuchMethodException: Baz.baz(Bar)
It's easier just to match on the name:
scala> classOf[Baz].getMethods.find(_.getName == "baz") map (_.invoke(b,p)) getOrElse -1
res5: Any = 1
or filter on the number of params for poor man's overloading resolution, then maybe filter on all args having conforming types.
The notation for accidentally getting the object is in fact:
scala> classOf[Option$]
res8: Class[Option$] = class scala.Option$
Upvotes: 1
Reputation: 11666
Answer: classOf[Option[_]]
Weird! Suddenly classOf[Option[_]]
works. I feel sure I tested once or twice before I submitted the question :-( Perhaps the IDE didn't have time to save the file before I recompiled, weird.
I don't know if I should delete the question. Or perhaps I should leave it as is, in case classOf[Option[_]]
isn't obvious to everyone.
Upvotes: 1