본문 바로가기
Android & Kotlin/Kotlin

[Kotlin Dispatch] 동적, 정적 디스패치 (Dynamic, Static Dispatch)

by 말린밴댕이_공부 2024. 5. 2.
반응형

 

디스패치(Dispatch) : 프로그램이 어떤 메소드를 호출할 것인가를 결정하여 그것을 실행하는 과정을 말함

동적 디스패치(Dynamic dispatch) : 실행 시점에 객체 타입에 따라 동적으로 호출될 대상 메서드를 결정하는 방식

정적 디스패치(Static Dispatch) : 컴파일 시점에 알려진 변수 타입에 따라 정해진 메서드를 호출하는 방식

 

 

정적 디스패치(static dispatch):

컴파일 시점에 알려진 변수 타입에 따라 정해진 메서드를 호출하는 방식인 디스패치

주로 오버로딩에서 발생하며 컴파일러는 함수 호출시 전달되는 인자의 타입과 개수를 기반으로 적절한 함수를 선택하게 된다.

아래의 add 예시를 보게 되면 이해가 편하다.

fun add(a: Int, b: Int): Int {
    return a + b
}

fun add(a: Double, b: Double): Double {
    return a + b
}

fun main() {
    val resultInt = add(3, 5)
    val resultDouble = add(3.0, 5.0)
}

두가지의 예시를 보게 되면 add 함수는 두가지가 오버로딩 되어있으며

정적 디스패치를 통해 각각 add(Int, Int) / add(Double, Double) 가 호출이 됨

 

동적 디스패치(dynamic dispatch):

실행 시점에 객체 타입에 따라 동적으로 호출될 대상 메서드를 결정하는 방식인 디스패치

주로 상속과 오버라이딩(overriding)에서 발생하며 서브클래스가 슈퍼클래스의 메소드를 재정의 하는 경우 실행시간에 객체의 실제 타입을 확인하고 해당하는 메소드의 구현을 호출하게 됨

예시

open class Shape {
    open fun draw() {
        println("draw shape")
    }
}

class Circle : Shape() {
    override fun draw() {
        println("draw circle")
    }
}

class Rectangle : Shape() {
    override fun draw() {
        println("draw rectangle")
    }
}

fun main() {
    val shape1: Shape = Circle()
    val shape2: Shape = Rectangle()

    shape1.draw()
    shape2.draw() 
}

각 Circle 클래스와 Rectangle클래스는 Shape클래스를 상속하고 draw를 오버로딩을 합니다.

shape1,shape2는 각각 Circle, Rectangle 객체를 참조하고 있지만 호출할 때는 실행시간에 결정이 되며 동적 디스패치라고 할 수 있다.

 

 

 

확장 함수는?

open class View {
    open fun click() = println("view Clicked")
}

class Button : View(){
    override fun click()  = println("Button Clicked")
}

fun View.showOff() = println("ShowOff View")
fun Button.showOff() = println("ShowOff Button")


fun main() {
    val view : View = Button()

    view.click()
    view.showOff()
}

 

 

위의 main의 Click, showOff 결과는 과연 어떤 디스패치가 사용될까?

 

 

 

 

 

Clicked

Button이 view의 하위 타입이기 대문에 view 타입 변수를 선언해도 Button 타입 변수를 그 변수에 대입 할 수 있음

위의 결과를 보면 오버라이드한 Button의 click이 호출이 된다. -> 동적 디스패치

 

ShowOff

main에서 view는 Button 객체를 참조하고 있지만 변수의 선언 타입은 View이다.

따라서, view.showOff()를 호출할때  view는 View에 대한 확장 함수인 showOff를 선택하게 됨

 

확장함수 -> 클래스의 일부가 아니며 클래스 밖에 선언된다. / 확장함수는 오버라이드 할 수 없다.

 

*참고 : Kotlin In Action*

반응형

댓글