본문 바로가기
Kotlin

Reflection

by 봄석 2019. 6. 8.

kotlin - Reflection

Reflection에 대하여 알아보도록 하겠습니다.

 

 

1) Reflection이란 ??

Reflection의 단어의 뜻은  '반사'  입니다 .  

자신을 반사하여  보여준다 !라고  생각하면 될것같습니다

리플렉션은 런타임시 자신의 프로그램 구조에 대한 내성 검사를 허용하는 언어 및 라이브러리 기능 세트입니다.

코틀린은 언어에서 함수와 프로퍼티를 일급 시민으로만들고,

런타임에 함수나 프로퍼티의 타입 또는 이름을 학습하는 것은 단순하게 함수적 스타일
또는 반응적 스타일을 사용하는 것과 밀접하게 연관되어 있습니다.

 

2) 클래스 참조

가장 흔히 볼수있는 Refection 은 클래스 참조 입니다 .

val c =ReflectionTest::class

 

::연산자로 ReflectionTest라는 클래스를 참조합니다.

리턴값은 KClass 입니다 .

코틀린의 클래스참조는 자바와 같지않으므로 , 자바클래스의 참조를 얻으려면 .java를 붙여줍니다 .

val c =ReflectionTest::class.java

 

3) 함수 참조

    fun isOdd(a: Int) = a % 2 != 0

위와같이 홀수를 걸러내주는 함수가 있다면 , 위의 함수를 isOdd(5) 이런식으로 사용할 수 있을것입니다 .

 

하지만 함수형 값으로 사용할 수도 있습니다 .(예 : 다른함수로전달 ) 이럴떄   ' :: '연산자를  사용합니다 .

    fun helloReflection() {
        val number = listOf(1, 2, 3, 4)
        println(number.filter(::isOdd))

    }

 isOdd의 함수 유형은  (Int)-> Boolean입니다.


 

또다르게 사용해 본다면

fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove"

위는 isOdd함수의 오버로딩입니다.

val predicate: (String) -> Boolean = ::isOdd 

명시적으로 지정된 유형의 변수에 메소드 참조를 저장하여 필요한 컨텍스트를 제공 할 수 있습니다.

 


또는 우리가 클래스의 멤버 나 확장 함수를 사용해야한다면, 예를 들어 자격이 필요합니다 String::toCharArray.

확장 함수에 대한 참조를 사용하여 변수를 초기화하더라도 유추 된 함수 유형에는 수신기가 없습니다.

(수신기 객체를 수락하는 추가 매개 변수가 있음). 

함수 대신에 리시버를 사용하려면, 타입을 명시 적으로 지정하면 됩니다.

val isEmptyStringList: List<String>.() -> Boolean = List<String>::isEmpty
val empryList = emptyList<String>()
println(isEmptyStringList(empryList))

//true

 

응용 예

fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
        return { x -> f(g(x)) }
    }

fun length(s: String) = s.length

val oddLength = compose(::isOdd, ::length)
val strings = listOf("a", "ab", "abc")
println(strings.filter(oddLength))

//[a, abc]

4) 프로퍼티 참조

  val x = 1

    @Test
    fun getPropertyTest() {
        println(::x.get())
        println(::x.name)
    }
    
    //1
    //x

표현식 ::x의 반환값은 Kproperty

val 은 immutable이므로 KProperty 입니다 . get()만 가능합니다.

이 객체를 사용하면 속성을 사용하여 속성 이름을 사용하여 KProperty<Int>값을 읽 get()거나 속성 이름을 검색 할 수 name있습니다.

 


var y = 1

    @Test
    fun setPropertyTest() {
        ::y.set(2)
        println(y)
    }
}


//2

변경 가능한 속성에 대해 예를 들어 var y = 1, 

::y의 반환값은 KMutableProperty입니다 .

get(), set()모두 가능합니다.

 


ex)문자열 배열의 length로 배열변경

 @Test
    fun lengthTest(){
        val strs = listOf("a", "bc", "def")
        println(strs.map(String::length)
        )
    }

    //[1, 2, 3]

5) 생성자 참조

    class Foo

    fun function(factory: () -> Foo) {
        val x: Foo = factory()
    }

    @Test
    fun reperenceConstuctorTest(){
        function (::Foo)
    }

Foo라는  클래스의 기본생성자 참조하기

댓글