본문 바로가기

iOS/Swift

Swift) Static Dispatch & Dynamic Dispatch (2/2)

 

 

안녕하세요:) 소들입니당~~

오늘 밀린 댓글에 대한 답글을 쭉~ 다는데

저를 선생님이라 부르시는 분들이 많더라구요...ㅋㅋㅋㅋ💦

어릴 때 국어선생님과 작가가 꿈이었는데.. 못 이룬 꿈을 이렇게...?😎

 

뭐쨌거나 오늘은 Dispatch에 대한 공부 2탄!!!!

저번 포스팅에서 Dispatch의 종류에 대해 공부를 했고,

Swift의 Value Type, Reference Type, Protocol에선 어떤 Dispatch를 사용하는지까지 봤어요!

 

이번 포스팅에선 조금 더 심화된 내용인

Value Type, Reference Type, Protocol을 확장(extension)할 경우,

어떤 Dispatch가 사용되는지에 대해서 알아볼 거예요 호호

 

어려운 내용이라 혹시라도 이해가 안가거나 틀린 내용이 있으면 꼭 댓글 주세요!

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. Value Type "확장(exension)"에서의 Dispatch

 

상속의 가능성이 없기 때문에, 확장(exension)을 해도 Static Dispatch로 동작한다

 

 

struct Human {
    func sayHello() {
        print("Hello Human!")
    }
}
 
extension Human {
    func sayHo() {
        print("Ho~~")
    }
}
 
let sodeulHuman = .init()
sodeul.sayHello()           // Static Dispatch
sodeul.sayHo()              // Static Dispatch

 

 

그러하다 😶‍🌫️

 

 

 

 

2. Reference Type "확장(exension)"에서의 Dispatch

 

여러분 Class를 확장(extension)하여 메서드를 추가한 경우,

서브 클래스에서 오버라이딩이 불가하단 사실은 알고 계신가요? 깔깔

 

   

class Human {
    func sayHello() {
        print("Hello Human!")
    }
}
 
extension Human {
    func sayHo() {
        print("Ho~~")
    }
}
 
class Teacher: Human {
    override func sayHo() {         // error! Overriding non-@objc declarations from extensions is not supported
        
    }
}
 

 

 

swift에서 extension으로 메서드를 추가할 경우,

non-@objc일 경우 메서드 오버라이딩이 불가능하다능ㅋ

 

물론 @objc를 붙여주면 오버라이딩이 가능해지긴 함!!

(Objective-C의 런타임의 힘🔥을 빌리는 것)

 

그러나, @objc 힘을 빌리지 않는 일반적인 경우

확장(extension)을 통해 메서드를 추가할 경우 오버라이딩 자체가 불가능하기 때문에

 

 

let sodeulHuman = .init()
sodeul.sayHello()           // Dynaimc Dispatch
sodeul.sayHo()              // Static Dispatch

 

 

이때 sayHo라는 메서드는 무조건

Human이란 클래스의 extension 메서드가 불리는 것이 보장되기 때문에

이때는 Static Dispatch로 동작함 :)

 

 

 

 

3. Protocol "확장(exension)"에서의 Dispatch

 

프로토콜은 총 두 가지 경우로 나눠서 볼 수 있음

 

 

 

3-1. Protocol에 선언만 되어있는 메서드를 extension을 통해 default 메서드를 구현한 경우

 

 

protocol Human {
    func sayHello()
}
 
extension Human {
    func sayHello() {
        print("Hello Human!")
    }
}
 
class Student: Human { }

class Teacher: Human {
    func sayHello() {
        print("Hello Teacher!")
    }
}

 

 

protocol에 선언된 sayHello라는 메서드는 보통 채택하는 클래스에서 필수적으로 구현해야 하지만,

extension을 통해서 default로 구현을 해놓을 수도 있음!!

extension을 통해 default 구현을 해놓은 경우, 해당 프로토콜을 채택해도 해당 메서드에 대한 구현이 필수적이지 않음

(만약 구현이 안 되어 있는 상태에서 해당 메서드를 호출할 경우, extension에 작성된 default 메서드가 불리기 때문)

 

 

var sodeulHuman = Student.init()
sodeul.sayHello()       // Hello Human!
 
sodeul = Teacher.init()
sodeul.sayHello()       // Hello Teacher!
 

 

 

따라서 Student 같이 직접 sayHello 구현하지 않은 경우 extension에 작성된 sayHello가 불리지만,

Teacher과 같이 sayHello를 직접 클래스 내에서 구현한 경우,

extension보다 직접 구현한 메서드가 우선순위가 높아 Teacher 클래스 안의 sayHello가 불리게 됨

 

정리하자면,

extension으로 프로토콜 선언부의 default 메서드를 구현하면

Human 프로토콜을 채택한 클래스 내에서 직접 메서드를 정의하지 않은 경우(Student),

extension으로 구현된 default 메서드가 불려야 하고,

Human 프토토콜을 채택한 클래스 내에서 직접 메서드를 정의한 경우(Teacher),

해당 클래스에 정의된 메서드가 불려야 하기 때문에,

이때는 어느 한 타입에서만 불린다! 하고 단정지을 수 없어서 Dynamic Dispatch로 동작함

 

 

 

3-2. Protocol에 선언되어있지 않은 메서드를 추가로 구현한 경우

 

 

protocol Human { }
 
extension Human {
    func sayHello() {
        print("Hello Human!")
    }
}
 
class Student: Human { }

class Teacher: Human {
    func sayHello() {
        print("Hello Teacher!")
    }
}

 

 

만약 이렇게 Human 프로토콜에 선언되어 있지 않는데

sayHello란 메서드를 extension을 통해 추가 구현한 경우 어떻게 동작하냐면,

 

 

var sodeulHuman = Student.init()
sodeul.sayHello()       // Hello Human!
 
sodeul = Teacher.init()
sodeul.sayHello()       // Hello Human!
 

 

 

당연히 Student 클래스에는 sayHello란 메서드가 없으니 extension에서 구현한 sayHello가 불리지만,

Teacher이란 클래스는 sayHello란 메서드를 자기 클래스 내에서 구현 했음에도 불구하고,

현재 sodeul이란 변수의 타입이 Human이란 프로토콜의 타입이기 때문

해당 프로토콜의 extension에서 구현된 sayHello 메서드가 실행되어 버림

 

이처럼,

Protocol에 선언되지 않은 메서드를 추가로 extension으로 구현한 경우엔

해당 클래스 내에서 똑같은 메서드를 작성하더라도,

"해당 프로토콜 타입"에선 무조건 extension으로 구현된 메서드만 실행되기 때문에

이때는 Static Dispatch로 동작함

 

 

+ 헷갈리실 거 같은데,

위에서 sodeul의 타입이 Human이라는 프로토콜의 타입이기 때문에 이런 일이 생기는 것임

만약 다음과 같이 Teacher로 타입을 명시할 경우, 이땐 Teacher 클래스 내에 있는 sayHello가 불림!

 

 

var sodeulTeacher = .init()
sodeul.sayHello()       // Hello Teacher!

 

 

이렇게!!! 🤗

 

 

 

 

 

.

.

.

이번 포스팅까지 해서 Swift에서 Dispatch에 대해선 어느정도 정리를 한 것 같아요!!!

많이 공부하고 쓰는데,,, 아직 이해가 부족한 부분이 있어서

혹시 잘못된 부분이나 궁금점 있으시면 꼭 댓글 남겨주시길 바랍니당 :)

이제 다음 포스팅에선 궁극의 목표였던 Dispatch를 이용한 Swift 성능 개선에 대해 배워봅시다 하하핳

(거대해보이지만 별건 없음ㅎ;)

 

 

 

참고 자료:

 

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



Calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
최근 댓글
Visits
Today
Yesterday