ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] Dynamic Dispatch / Static Dispatch
    개발/Swift 2021. 12. 20. 17:03

    ios 면접 질문 리스트를 보던중 이런 문제를 보았다.

    class B: A 일 때 A와 B 둘다 func one()이라는 함수가 있으면
     B 인스턴스나 A 인스턴스에서 이 함수를 호출했을때 
    둘 중 어떤 함수를 호출할지 어떻게 판단하는가?
    

    B는 자식 클래스, A는 부모 클래스이다

    B와 A 모두 one()함수를 정의했다면

    B(인스턴스).one()을 호출하면 B의 함수를

    A.one()을 호출하면 A의 함수를 호출할것이다.

     

    그러면 만약 자식 클래스인 B가 상속을 받지 않았다면?

    one 함수를 오버라이딩 하지 않았다면? 어떻게 어떤 함수를 쓸지 결정할수 있을까?

    이게 가능한 것은 어떤 함수를 호출할지 컴파일 단계에서 결정짓지 않아서 가능하다.

    let instanceA = A()
    instanceA.one() //결정 시점
    
    let instanceB = B()
    instanceB.one()
    

    즉 어떤 함수를 호출할지 런타임에 결정된다.

    그리고 이것을 Dynamic Dispatch라 한다.

     

    Dynamic Dispatch 의 반대로는 Static Dispatch라고 한다.

    이거는 컴파일 시점에서 어떤 함수를 호출 할지 결정된다.

    struct타입의 경우 상속을 받을수 없다. 그래서 돌아볼것도없이 static dispatch를 사용한다.

     

    class의 경우 디폴트로 dynamic disptch를 사용한다. 상속을 받을수도 있기 떄문이다.

    dynamic dispatch는 컴파일러로 하여금 vtable(?)이라는 것을 보고 적합한 함수를 찾게한다.

    (이것을 indirect function call 이라고도함 ↔ direct function call)

    그러므로 그만큼 비용이 발생한다. 따라서 필요하지 않은경우 static을 사용하도록 유도해야한다.

     

    Static Dispatch을 사용하기위한 방법

     

    클래스 에서 static dispatch를 유도하기 위해 final 을 사용하면 좋다.

    하지만 final 을 사용하면 상속을 막는다. 즉 해당 클래스를 상속하지 않는다면 final을 사용하면 좋다.

    혹은 해당 클래스를 상속하려 하지만 몇개의 메소드나 프로퍼티는 상속하고 싶지 않을때

    함수 앞에 final을 붙여 상속을 막을수 있다.

    class A {
        
        final point = 0
        final func test(){
            print("Test A")
        }
    }
    
    

    private 도 마찬가지이다. private은 해당 클래스의 메소드나 프로퍼티를 감출때 사용한다.

    private을 사용하면 해당 함수를 override 할수가없다.

    final로 추론되어 static dispatch를 사용한다.

     

     

    WMO (whole module optimization) 은 swift 파일들을 병렬적으로 컴파일 하지않고

    전체 swift 파일들을 한번에 컴파일한다. 자동으로 override 되지 않은 메소드에 final을 붙여 static dispatch

    를 유도한다. 관련 세팅은 여기서 한다.

    참조 :https://velog.io/@dvhuni/Reducing-Dynamic-Dispatch

    https://onemoonstudio.tistory.com/7

    댓글

Designed by Tistory.