Получение экземпляра объекта по строковому имени в scala - PullRequest
24 голосов
/ 16 декабря 2009

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

package myPackage
object myObject

... тогда есть что-нибудь подобное:

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

Ответы [ 4 ]

44 голосов
/ 10 июня 2013

В 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)
12 голосов
/ 16 декабря 2009

В 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.

11 голосов
/ 11 января 2010

Приспособление к ответу Томаса Юнга выше: вам лучше было бы сказать «компаньон» [List.type], потому что а) это должен быть стабильный способ обращения к нему, не зависящий от схемы искажения имени и б) вы получите неснятый типы.

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)
1 голос
/ 16 декабря 2009

Запретить трюки с отражением вы не сможете. Обратите внимание, например, на то, как метод companion определен в коллекциях Scala 2.8 - именно там экземпляр класса может получить объект-компаньон, что в противном случае невозможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...