2009-12-16 2 views
22

문자열 이름으로 정의 된 개체 (또는 "단독 개체"또는 "동반 개체"... 클래스 제외)가 필요합니다. 내가 가지고있는 경우 즉, :개체 이름을 스칼라로 문자열 이름으로 가져 오기

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

답변

12

스칼라는 여전히 반사 API를 누락되었습니다

package myPackage 
object myObject 

... 다음 이런 일이있다.

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) 

이 방식 스칼라에 따라 달라집니다

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) 

가 직접 클래스를 사용할 수있는 객체 유형이 지정되지 않은 동반자를 얻으려면 : 당신은 동반자 객체 클래스를로드하여 동반자 개체의 인스턴스를 얻을 수 있습니다 Java 클래스에 매핑됩니다.

+1

신성한 소처럼 할 수 있습니다. 이 구문이 스칼라 사양의 고정 부분인지 (언어의 다른 부분처럼 고정되어 있음) 알고 있습니까? 이것에 의존하는 것은 나쁜 생각처럼 보입니다. 그리고 내 목표는 코드를 더 명확하게 만드는 것이었기 때문에 * ... 감사합니다! – Dave

+0

그가 언급했듯이 스칼라에는 리플렉션 API가 아직 없으므로 Scala 사양에 해당하는지 여부에 관계없이 이것이 수행 할 수있는 유일한 방법입니다. 이 질문/답변이 1 년 이상 된 것을 확인했습니다. 여기에 뉴스가 있습니까? – pdinklag

1

반사 트릭을 제외하면 할 수 없습니다. 예를 들어, companion 메서드가 Scala 2.8 컬렉션에 정의 된 방법에 유의하십시오. 클래스의 인스턴스가 다른 객체를 가져올 수 있으므로 그렇지 않으면 불가능합니다.

+0

소스에 대한 링크를 추가 할 수 있습니까? –

+0

http://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala, 2.8의 Scaladoc 2에는 곧 2.7 에서처럼 소스에 대한 링크가 포함됩니다. –

11

위의 Thomas Jung의 대답에 대한 조정 : a) 이것은 mangling scheme에 의존하지 않고 이것을 참조하는 안정된 방법이어야하기 때문에 [List.type] 동반자라고 말하는 것이 좋습니다. 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) 
+0

아주 좋습니다! 내 취향에 조금 어색하지만 나는 이것을 사용할지도 모른다. – Dave

+0

이것이 List.make (3, "a")보다 나은가요? OP는 문자열 이름으로 객체를 가져 오려고했습니다 – IttayD

+1

고마워요! 이것은 내가 찾고 있었던 바로 그 것이다. 그것은 확실히 해킹이지만, 내가 관리 할 수 ​​있었던 것보다 덜 지저분합니다. –

34

스칼라 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)