[scala] reflection api 예시

scala 2016. 12. 21. 20:18


REPL에서 :type을 사용하면 타입을 볼 수 있다. 



scala> :type if (true) println("true")

Unit


scala> :type if (true) true

AnyVal



scala> :type false

Boolean


scala> :type "aaa"

String


scala> Map(1->"1", 2->"3") map (_._2)

res7: scala.collection.immutable.Iterable[String] = List(1, 3)


scala> :type Map(1->"1", 2->"3") map (_._2)

scala.collection.immutable.Iterable[String]



scala> :type -v Map(1->"1", 2->"3") map (_._2)

// Type signature

scala.collection.immutable.Iterable[String]


// Internal Type structure

TypeRef(

  TypeSymbol(

    abstract trait Iterable[+A] extends Traversable[A] with Iterable[A] with GenericTraversableTemplate[A,scala.collection.immutable.Iterable] with IterableLike[A,scala.collection.immutable.Iterable[A]] with Parallelizable[A,scala.collection.parallel.immutable.ParIterable[A]]


  )

  args = List(

    TypeRef(

      TypeSymbol(

        final class String extends Serializable with Comparable[String] with CharSequence


      )

    )

  )

)





스칼라 class에 대해 java 리플렉션(reflection)을 사용할 수 있다 .



trait Trait {
val m = 1
}

class Clazz extends Trait {
var m1 = 333333
var m2 = "aa"
}

object Execise extends App {
val clazz = classOf[Clazz]
val name = clazz.getName
println("name : " + name)

//println
val constructors = clazz.getConstructors
println("constructors : " + constructors.mkString(" "))

println
val methods = clazz.getMethods
println("methods : " + methods.mkString(" "))

println
val fields = clazz.getFields
println("fields : " + fields.mkString(" "))

println
val annotations = clazz.getAnnotations
println("annotations : " + annotations.mkString(" "))

println
val superClass = clazz.getSuperclass
println("superClass : " + superClass)

println
val typeParameters = clazz.getTypeParameters
println("typeParameters : " + typeParameters.mkString(" "))
}

결과는 다음과 같다. 



name : com.google.Clazz

constructors : public com.google.Clazz()


methods : public void com.google.Clazz.m1_$eq(int) public void com.google.Clazz.m2_$eq(java.lang.String) public int com.google.Clazz.m1() public java.lang.String com.google.Clazz.m2() public int com.google.SuperClazz.m() public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait() throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public java.lang.String java.lang.Object.toString() public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll()


fields : 


\3 1aY8n"%QQ"

-!AC*va8 \1{u")QC1A(8jiz"a Aq!A!#ncU 1/5 QCC8-7b ARCAJ]RDqAA1$nc}#S-9}"F

1#AyIEBaA !BaA72A!9Aa

)AA73+1CA-A#BA+aM\4-

AA[1wC&Q'RN\4 =!Ca1QNM0%KF$"H r!aM!11Q!

1!!)


superClass : class com.google.SuperClazz



스칼라의 classOf의 리턴타입은 java.lang.Class이다.(컴파일러에서 제대로 생성된다)

def classOf[T]: Class[T] = null

또한, 결과를 통해 추측할 수 있겠지만, 일부 내용을 파싱하면서 에러난 부분이 발생했다. 아직 scala 클래스 객체를 완벽히 소화한 상태는 아니다. 이는 스칼라에서 쓸 수 있는 TypeTags를 활용하면 의미있는 정보를 얻을 수 있다. 





먼저 스칼라의 ClassTag이다. ClassTag를 사용하면 컴파일러가 암시 ClassTag를 생성한다. TypeTags의 약한 버전이다. 

import scala.reflect.ClassTag

case class Person(id: Int)

def makeArray[T: ClassTag] (elements: T*) = Array[T](elements: _*)

println(makeArray(1,2,3).mkString(" "))

println(makeArray("one", "two", "three").mkString(" "))

println(makeArray(1, "xxx").mkString(" "))

println(makeArray(Person(1), Person(2)).mkString(" "))

결과는 다음과 같다.


1 2 3

one two three

1 xxx

Person(1) Person(2)






다음은 TypeTag를 활용한 예시이다. 강력한 스칼라 reflection api이다. 

class SuperClazz {
val m = 1
}

class Clazz extends SuperClazz {
var m1 = 333333
var m2 = "aa"
}


import scala.reflect.runtime.universe._
def toType[T: TypeTag](t : T) = typeOf[T]

println(toType(1))
println(toType(false))
println(toType(new Clazz))
println(toType(List(1, "aa")))
println(toType(Seq(1, true, 3.14)))

val t = toType(2)
println(t.typeSymbol)
println(t.erasure)
println(t.typeArgs)
println(t.baseClasses)
println(t.companion)

println()
val t1 = toType(new Clazz)
println(t1.members)
println(t1.baseClasses)



결과는 다음과 같다.


Int

Boolean

com.google.Clazz

List[Any]

Seq[AnyVal]

class Int

Int

List()

List(class Int, class AnyVal, class Any)

Int.type


Scope{

  private[this] var m2: <?>;

  def m2_=: <?>;

  def m2: <?>;

  private[this] var m1: <?>;

  def m1_=: <?>;

  def m1: <?>;

  def <init>: <?>;

  val m: <?>;

  final def $asInstanceOf[T0](): T0;

  final def $isInstanceOf[T0](): Boolean;

  final def synchronized[T0](x$1: T0): T0;

  final def ##(): Int;

  final def !=(x$1: Any): Boolean;

  final def ==(x$1: Any): Boolean;

  final def ne(x$1: AnyRef): Boolean;

  final def eq(x$1: AnyRef): Boolean;

  final def notifyAll(): Unit;

  final def notify(): Unit;

  protected[package lang] def clone(): java.lang.Object;

  final def getClass(): java.lang.Class[_];

  def hashCode(): Int;

  def toString(): java.lang.String;

  def equals(x$1: Any): Boolean;

  final def wait(): Unit;

  final def wait(x$1: Long): Unit;

  final def wait(x$1: Long,x$2: Int): Unit;

  protected[package lang] def finalize(): Unit;

  final def asInstanceOf[T0]: T0;

  final def isInstanceOf[T0]: Boolean

}

List(class Clazz, class SuperClazz, class Object, class Any)





Posted by '김용환'

댓글을 달아 주세요