Devabc
Devabc

Reputation: 5311

Scala reflect string to singleton object

I'm looking for a way to convert a Scala singleton object given as a string (for example: package1.Main) to the actual instance of Main, so that I can invoke methods on it.

Example of the problem:

package x {
  object Main extends App {
    val objectPath: String = io.StdIn.readLine("Give an object: ") // user enters: x.B

    // how to convert the objectPath (String) to a variable that references singleton B?
    val b1: A = magicallyConvert1(objectPath)
    b1.hi()

    val b2: B.type = magicallyConvert2(objectPath)
    b2.extra()
  }

  trait A {
    def hi() = {}
  }

  object B extends A {
    def extra() = {}
  }
}

How can the magicallyConvert1 and magicallyConvert2 functions be implemented?

Upvotes: 0

Views: 626

Answers (2)

Devabc
Devabc

Reputation: 5311

For a normal class, this can be done using something like:

val b: A = Class.forName("x.B").newInstance().asInstanceOf[A]

But I found a solution for singletons, using Java reflections:

A singleton is accesible in Java under the name: package.SingletonName$.MODULE$ So you have to append "$.MODULE$", which is a static field. So we can use standard Java reflections to get it.

So the solution is:

def magicallyConvert1(objectPath: String) = {
  val clz = Class.forName(objectPath + "$")
  val field = clz.getField("MODULE$")
  val b: A = field.get(null).asInstanceOf[A]
  b
}

def magicallyConvert2(objectPath: String) = {
  val clz = Class.forName(objectPath + "$")
  val field = clz.getField("MODULE$")
  val b: B.type = field.get(null).asInstanceOf[B.type]
  b
}

But it would be interesting to still see a solution with Scala-Reflect en Scala-Meta.

Upvotes: 1

Arnon Rotem-Gal-Oz
Arnon Rotem-Gal-Oz

Reputation: 25929

take a look at scalameta http://scalameta.org it does what you want and more

Upvotes: 0

Related Questions