스칼라 리플렉션 

 참고: http://3x14159265.tumblr.com/post/57543163324/playing-with-scala-reflection

리플렉션에 대해서 생소하다면 먼저 자바 리플렉션 관련 읽을 거리를 읽어보세요.

1. 자바 클래스로더 이야기
2. 자바 리플렉션 사용하기 


스칼라 2.10에서 새로운 리플렉션 API 가 소개되었습니다. 

리플렉션으로 보통 우리는 

  1. 제네릭 타입을 포함하여 객체의 타입을 조사한다.
  2. 런타임에 클래스(파일 혹은 네트워크를 통해서 전해온 바이트를 통해) 객체를 생성한다.
  3. 그 객체의 메소드를 호출한다.


를 할 수 있게 됩니다.

하나씩 살펴 볼까요?  먼저 아래와 같이 임포트 해줍니다.

import scala.reflect.runtime.universe._


객체와 클래스들은 런타임에 클래스로더와 runtime mirror 를 이용하여 인스턴스화 될 수 있습니다.
객체와 클래르 생성이 약간 다릅니다.

def getObjectInstance(clsName: String): ModuleMirror = {
val mirror = runtimeMirror(getClass.getClassLoader)
val module = mirror.staticModule(clsName)
mirror.reflectModule(module).instance
}
def getClassInstance(clsName: String): Any = {
val mirror = runtimeMirror(getClass.getClassLoader)
val cls = mirror.classSymbol(Class.forName(clsName))
val module = cls.companionSymbol.asModule
mirror.reflectModule(module).instance
}

다음과 같은 object 가 있다고 가정 하면  (파일로 있어도 되고, 바이트 배열로 있어도 된다)

package models.entities
object User {
def findByUsername(username: String) = {
// database or whatever magic is done here ;)
}
}

런타임에 이 object 의 메소드를 호출 할 수 있습니다.  (즉 원격에서 클래스를 가져와서 호출해 줄 수도 있다는 의미. 예를들어 분산 컴퓨팅시 동일한 작업을 여러 컴퓨터에서 분산 시켜서 하고자 할 때도 사용 될 수 있겠지요.)

def invokeMethod(param: String) = {
val im =mirror.reflect(getObjectInstance("models.entities.User"))
val method = im.symbol.typeSignature.member(newTermName("findByUsername")).asMethod
im.reflectMethod(method)(param)
}

물론 스칼라의 새 리플렉션 API 는 훨씬 더 많은 것을 포함하고 있습니다.  다음 문서를 참고하세요. scala docs.


저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by [前草] 이승현 (wowlsh93@gmail.com)