rybosome
rybosome

Reputation: 5136

How to express type parameter bounds in methods?

In Scala, I need to execute code that fulfills the following requirement:

Pass a java.lang.Class into a factory method. The class passed to this method must extend the abstract class Project. I will instantiate this class, perform various actions, and return it.

Here's what I have...

object ProjectFactory {

    def create (clazz: java.lang.Class[T <: Project]): Project = {
        val newProject = clazz.newInstance
        /* snip */
        newProject
    }

}

abstract class Project

...and here is the error I am getting:

identifier expected but <: found

I know this is just a syntax issue - how do I express this logic?

Upvotes: 1

Views: 156

Answers (2)

DaoWen
DaoWen

Reputation: 33019

You need to declare the type parameter after the method name, not at the use site:

object ProjectFactory {

    def create[T <: Project](clazz: java.lang.Class[T]): Project = {
        val newProject = clazz.newInstance
        /* snip */
        newProject
    }

}

abstract class Project

I'm not an expert with Scala's reflection libraries, but I think this might be cleaner:

object ProjectFactory {

    def create[T <: Project: Manifest]: Project = {
        val newProject = classManifest[T].erasure.newInstance.asInstanceOf[Project]
        /* snip */
        newProject
    }

}

abstract class Project

That way you don't have to explicitly pass in a class object—you just parameterize the method with the type you want. Again, I bet there's a better way to do this, so I'd appreciate feedback from those with more experience in this area.

Also, I think Scala 2.10 has dropped Manifests in favor of ClassTags or something like that...

Upvotes: 6

om-nom-nom
om-nom-nom

Reputation: 62835

You were close:

object ProjectFactory {
    def create[T <: Project](clazz: java.lang.Class[T]): Project = {
        val newProject = clazz.newInstance
        /* snip */
        newProject
    }
}

abstract class Project

Upvotes: 2

Related Questions