Thursday, June 4, 2009

GetAnyClass Tip

I've been having some trouble with calling getClass on generic/primitive types.
It seems that it's a known issue with scala that
wontfix and hence this code won't compile

def convert[A,B](instance : A, toClass : Class[B]) : Option[B] = {
//Fails here with the error below
instance.getClass
...Rest of implementation...
}


(The error):

:6: error: type mismatch;
found : A
required: ?{val getClass: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (Any)scala.runtime.StringAdd
and method any2ArrowAssoc in object Predef of type [A](A)ArrowAssoc[A]
are possible conversion functions from A to ?{val getClass: ?}
instance.getClass
^


the problem has a quick fix though suggested by paulp on the #scala irc channel on Freenode:

you can encapsulate that though:
scala> def getAnyClass(x: Any) = x.asInstanceOf[AnyRef].getClass
getAnyClass: (x: Any)java.lang.Class[_ <: java.lang.Object
casting to AnyRef (for this purpose) is a no-op on non-primitives, so...
you could plant that as an implicit if you want so 1.getAnyClass will work.
what this translates to is basically defining a class like this somewhere in your project:

/** Predef for brewmaster, maybe package objects will obsolete this
*/
private[brewmaster] object Brewdef {
implicit def any2GetAnyClass(x : Any) = new GetAnyClass(x)
class GetAnyClass(val x : Any) {
def getAnyClass = x.asInstanceOf[AnyRef].getClass
}
}


then chaning the code above slightly to use the .getAnyClass method it with
Publish Post

import Brewdef._
def convert[A,B](instance : A, toClass : Class[B]) : Option[B] = {
instance.getAnyClass
...
}


voila!
this will also allow things like 5.getAnyClass to compile (.getClass fails)

No comments: