Search code examples
genericsscalamanifestscala-2.8parameterization

Generic object load function for scala


I'm starting on a Scala application which uses Hibernate (JPA) on the back end. In order to load an object, I use this line of code:

val addr = s.load(classOf[Address], addr_id).asInstanceOf[Address];

Needless to say, that's a little painful. I wrote a helper class which looks like this:

import org.hibernate.Session

class DataLoader(s: Session) {
  def loadAddress(id: Long): Address = {
    return s.load(classOf[Address], id).asInstanceOf[Address];
  }
  ...
}

So, now I can do this:

val dl = new DataLoader(s)
val addr = dl loadAddress(addr_id)

Here's the question: How do I write a generic parametrized method which can load any object using this same pattern? i.e

val addr = dl load[Address](addr_id)

(or something along those lines.)

I'm new to Scala so please forgive anything here that's especially hideous.


Solution

  • Here it is:

    import org.hibernate.Session
    class DataLoader(s: Session) {
      def load[A](id: Long)(implicit m: Manifest[A]): A = {
        return s.load(m.erasure, id).asInstanceOf[A];
      }
    }
    

    EDIT -- Or, to ensure that any casting error -- as a result of hibernate returning the wrong object -- will happen inside load, like this:

    import org.hibernate.Session
    class DataLoader(s: Session) {
      def load[A](id: Long)(implicit m: Manifest[A]): A = {
        return m.erasure.asInstanceOf[Class[A]].cast(s.load(m.erasure, id));
      }
    }
    

    On Scala 2.8 you can also write it like this:

    import org.hibernate.Session
    class DataLoader(s: Session) {
      def load[A : Manifest](id: Long): A = {
        return s.load(manifest[A].erasure, id).asInstanceOf[A];
      }
    }
    

    You can combine it with an implicit session as well, as suggested by Chris:

    def load[A](id: Long)(implicit m: Manifest[A], s: org.hibernate.Session): A = {
      return s.load(m.erasure, id).asInstanceOf[A];
    }
    

    Note that you can't combine context view notation (A : Manifest) with additional implicit parameters.