Подтвердить что ты не робот

Получение экземпляра объекта по имени строки в scala

Мне нужен объект (или "singleton object" или "comanion object"... ничего, кроме класса), определяемый именем строки. Другими словами, если у меня есть:

package myPackage
object myObject

... тогда есть что-то вроде этого:

GetSingletonObjectByName("myPackage.myObject") match {
  case instance: myPackage.myObject => "instance is what I wanted"
}
4b9b3361

Ответ 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 - он есть, поэтому экземпляр класса может получить объект-компаньон, что в противном случае невозможно.