객체 지향 언어의 특징인 다형성을 Overloading과 Overriding을 통해 구현할 수 있다.
다음과 같이 override한 경우, 실제 호출될 method를 스위프트는 어떻게 결정할까?
class Parent {
func someMethod() {
print("Parent method")
}
}
class Child: Parent {
override func someMethod() {
print("Child method")
}
}
let object: Parent = Child()
object.someMethod() // ?
스위프트는 class(참조 타입)의 경우 dynamic dispatch 방식을 채택하고 있다.
컴파일 시점이 아닌, 런타임에 호출될 타입을 결정하는 dynamic dispatch가 이루어진다.
따라서 위의 예제에서는 실제 타입인 Child
의 method가 호출된다.
Dynamic Dispatch가 아닌 Static Dispatch 방식으로 타입을 결정할 수도 있다.
Static Dispatch는 컴파일 시점에 호출할 타입을 결정한다.
따라서, Dynamic Dispatch보다 성능상 이점이 있지만 다형성을 활용할 수 없다는 단점이 있다.
Increasing Performance by Reducing Dynamic Dispatch
공식 블로그에서 Static Dispatch를 유도하기 위한 방법으로 다음 3가지를 제시하고 있다.
final
키워드 사용private
키워드 사용오버라이드가 필요 없다면 final
키워드 사용
: final
키워드를 붙인 class, method, property는 오버라이딩이 불가능하므로, Static Dispatch가 일어난다.
private
을 사용하는 경우에도, 한 파일 안에서만 참조(접근)되는 것이 보장되므로, 컴파일러가 Static Dispatch로 타입을 결정 할 수 있다.
WMO(Whole Module Optimization) 옵션을 활성화한다면 모듈의 파일을 개별적으로 컴파일 하지 않고 모듈 전체를 하나의 덩어리로 취급해서 컴파일 하기 때문에, internal
키워드만으로 다른 모듈에서 override 되지 않음을 보장(final 추론 가능)할 수 있다.
(xcode 8부터 default가 활성화)
읽어보면 좋은 레퍼런스들
https://brunch.co.kr/@joonwonlee/14
https://swift.org/blog/whole-module-optimizations/