Kotlin Inline Function

HEETAE HEO·2022년 6월 27일
0
post-thumbnail

Inline function

인라인(Inline) 키워드는 자바에서는 제공하지 않는 코틀린만의 키워드입니다. 이러한 인라인 키워드를 사용하면 얻을 수 있는 장점들에 대해서 설명해보겠습니다.

람다식을 사용

인라인 함수를 사용한다면 람다식을 사용했을 때 무의미한 객체 생성을 막을 수 있습니다. 글로 설명하는 것보다는 코드로 설명해드리겠습니다.

아래 코드에서는 파라미터로 정수형 데이터와 람다식을 받는 someMethod()가 있고 내부적으로 람다를 호출한 뒤 전달받은 정수를 2배 늘려 반환하는 형태의 동작을 하게됩니다.

fun main(args: Array<String>) {
	var a = 2
    println(someMethod(a, {println("some function")}))
    
    fun someMethod(a : Int, func: () -> Unit) : Int {
    	func()
        return 2*a
    }

함수를 매개변수로 전달하고 함수를 반환할 수 있는 고차함수입니다. 그러나 그것들이 객체로 저장된다는 사실은 메모리 오버헤드로 인해 때때로 사용에 불리할 수 있습니다. 문제는 각 개체에 메모리 힙에 공간이 할당되고 이 메서드를 호출하는 메서드에도 공간이 할당된다는 것입니다.

이러한 문제점을 해결하기 위해서 메서드 앞에 inline을 달아주는 것입니다.

inline fun someMethod(a: Int, func: () -> Unit) : Int {
	func()
    return 2*a

기본적으로 inline 컴파일러에 이러한 함수와 매개변수를 호출 사이트에 복사하도록 지시합니다. 마찬가지로 inline 키워드는 지원 필드가 없는 속성 및 속성 접근자와 함께 사용할 수 있습니다.

람다식에 로컬 변수 사용

로컬 변수를 람다에서 사용한다면 어떻게 동작하는지 알아보겠습니다.

fun doSomething(){
	val greetings = "Hello" // Local variable
    doSomethingElse {
    	println("$greetings from lambda") // Variable capture
    }
}

컴파일 된 코드는 아래와 같습니다. 람다식에서 사용하는 지역 변수는 아래와 같이 Function 객체의 생성자의 변수로 들어가는 것을 확인할 수 있습니다.

public static final void doSomething() {
	String greetings = "Hello"
    doSimethingElse(new Function(greetings) {
    	public final void invoke() {
        	System.out.println(this.$greetings + "from lambda");
        }
    });
}

객체에 변수가 추가되었습니다. 즉, 객체의 메모리 사용량이 늘어났다는 것입니다. 이것을 볼때 이 경우 인라인 함수를 사용하면 좀 더 나은 성능을 보장할 수 있을거라는 것을 알 수 있습니다.

reified 키워드

reified는 다음과 같이 정의할 수 있습니다. reified는 inline에서만 사용할 수 있기 때문에 inline으로 함수를 정의하였고 Generics의 타입 T앞에 reified 키워드를 써주면 됩니다.

inline fun <reified T> function(argument: T)

위에서 구현한 예제를 reified 키워드를 사용하여 다시 구현한다면

refied 키워드를 사용했기 때문에 T::class 처럼 클래스의 타입 정보를 얻을 수 있습니다. 그래서 타입 정보를 인자로 넘기지 않아도 Runtime에 타입 정보를 알 수 있습니다.

inline fun <reified T> printGenerics(value: T) {
    when (T::class) {
        String::class -> {
            println("String : $value")
        }
        Int::class -> {
            println("Int : $value")
        }
    }
}

printGenerics1("print generics function")
printGenerics1(1000)

위의 코드를 실행해보면 다음과 같습니다.

String : print generics function
Integer : 1000

profile
Android 개발 잘하고 싶어요!!!

0개의 댓글