카테고리 없음

[Swift] 동적디스패치(Dynamic Dispatch) 와 Private & final 사용

덤벨로퍼 2021. 10. 7. 14:45

디스패치란 어떤 메소드를 쓸지 결정하고 사용하는 과정이다.

class MotherClass {
  func printHello() {
    print("hello")
  }
}

class ChildClass: MotherClass { }

let helloClass: MotherClass = ChildClass()
helloClass.printHello()

위의 코드를 보면 printHello() 메소드는 MotherClass 에 구현이 되어있으며

ChildClass 는 MotherClass를 상속 받고있지만 printHello() 메소드를 오버라이드 하지 않았다.

helloClass 객채는 ChildClass 이지만

이런경우 마지막 helloClass.printHello() 메소드는 MotherClass의 printHello() 메소드가 호출이 된다.

이것은 이미 우리가 당연히 생각했던 결과이다.

 

그러나 다음은 어떨까? 

class MotherClass {
  func printHello() {
    print("hello")
  }
}

class ChildClass: MotherClass { 
	override func printHello() {
      print("hello mom")
    }
}

let helloClass: MotherClass = ChildClass()
helloClass.printHello()

ChildClass 에서 printHello()메소드를 오버라이드 했다.

이러면 helloClass는 ChildClass 이므로 ChildClass의 printHello() 메소드가 실행될것이다.

이렇게 어떤경우는 부모의 메소드 어떤경우는 자식의 메소드를 사용한다.

이것을 가능하게 해주는것이 동적 디스패치이다.

 

상속하거나 받은 클래스에서는 동적 디스패치를 통해 어떤 메소드를 사용할지 결정한다.

그런데 어떤걸 쓸지 고민하는 과정이 컴파일 시점이 아닌 런타임시점에서 한다는것이 문제다.

그말은 런타임 시점에서 추가적인 연산이 필요하여 오버헤드가 발생된다.

 

반대로 struct 타입같은경우 상속이 불가능 하다. 따라서 어떤걸 쓸지 고민하지 않아도된다.

이를 정적 디스패치라 부른다. 정적 디스패치는 동적 디스패치와 반대로 고민하지 않아도 된다.

그말은 오버헤드가 발생되지 않는다.

 

여기서 포인트는 상속하거나 받지 않을 메소드는 굳이 동적 디스패치가 필요없다 라는 것이다.

그런경우 정적 디스패치를 사용한다면 오버헤드를 줄이수 있을것이다.

이것을 가능하게 해주는것이 final & private 이다.

final 을 사용하면 해당 클래스의 상속을 제한해버린다 즉 상속을 못하므로 정적 디스패치를 사용한다.

class MotherClass {
  final func printHello() {
    print("hello")
  }
}

class ChildClass: MotherClass { }

let helloClass: MotherClass = ChildClass()
helloClass.printHello()

이렇게 자식에서 어차피 오버라이드 안할거면

final 을 붙여 정적 디스패치를 사용할수있다.

 

또 private 키워드는 private가 붙은 메소드나 프로퍼티를 사용하는것을 해당 class 내로 제한한다.

private 또한 final 처럼 정적 디스패치를 사용한다.

 

 

 

 

 

 

 

참조

 

https://jcsoohwancho.github.io/2019-11-01-Swift%EC%9D%98-Dispatch-%EA%B7%9C%EC%B9%99/

https://onemoonstudio.tistory.com/7

https://sihyungyou.github.io/iOS-method-dispatch/