Получение экземпляра объекта по имени строки в scala
Мне нужен объект (или "singleton object" или "comanion object"... ничего, кроме класса), определяемый именем строки. Другими словами, если у меня есть:
package myPackage
object myObject
... тогда есть что-то вроде этого:
GetSingletonObjectByName("myPackage.myObject") match {
case instance: myPackage.myObject => "instance is what I wanted"
}
Ответы
Ответ 1
Scala по-прежнему отсутствует API-интерфейс отражения. Вы можете получить экземпляр объекта-компаньона, загрузив класс объекта-компаньона:
import scala.reflect._
def companion[T](implicit man: Manifest[T]) : T =
man.erasure.getField("MODULE$").get(man.erasure).asInstanceOf[T]
scala> companion[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
Чтобы получить нетипизированный объект-компаньон, вы можете напрямую использовать класс:
import scala.reflect.Manifest
def companionObj[T](implicit man: Manifest[T]) = {
val c = Class.forName(man.erasure.getName + "$")
c.getField("MODULE$").get(c)
}
scala> companionObj[List[Int]].asInstanceOf[List$].make(3, "s")
res0: List[Any] = List(s, s, s)
Это зависит от того, как scala сопоставляется с java-классами.
Ответ 2
В scala 2.10 мы можем сделать так:
import scala.reflect.runtime.universe
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule("package.ObjectName")
val obj = runtimeMirror.reflectModule(module)
println(obj.instance)
Ответ 3
Корректировка на Томаса Юнга ответьте выше: вам лучше сказать спутника [List.type], потому что: a) это должен быть стабильный способ ссылаться на него, не зависящий от схемы смены имени, и b) вы получаете unerased типы.
def singleton[T](implicit man: reflect.Manifest[T]) = {
val name = man.erasure.getName()
assert(name endsWith "$", "Not an object: " + name)
val clazz = java.lang.Class.forName(name)
clazz.getField("MODULE$").get(clazz).asInstanceOf[T]
}
scala> singleton[List.type].make(3, "a")
res0: List[java.lang.String] = List(a, a, a)
Ответ 4
Запрет трюков с отражением невозможен. Обратите внимание, например, как метод companion
определен в коллекциях Scala 2.8 - он есть, поэтому экземпляр класса может получить объект-компаньон, что в противном случае невозможно.