Protocol의 상속과 조합

SteadySlower·2024년 3월 31일
0

iOS Development

목록 보기
38/38
post-custom-banner

오늘은 기존의 프로토콜을 가지고 새로운 프로토콜을 만드는 2가지 방법을 소개한다. 하나는 상속 (inheritance)으로 수직적 확장의 개념이고 다른 하나는 조합 (composition)으로 수평적 확장의 개념이다.

상속 (inheritance)

상속은 프로토콜의 수직적 확장으로 자식 프로토콜은 부모 프로토콜에 종속이 된다. 자식 프로토콜을 채택하여 구현한 객체는 반드시 자식 프로토콜 뿐만 아니라 부모 프로토콜에 정의된 속성과 메소드를 구현해야 한다.

부모 프로토콜에 다른 속성이나 메소드가 추가된 경우 반드시 자식 프로토콜에도 추가된다.

// 부모가 되는 프로토콜
protocol Student {
    var name: String { get }
    func study()
}

// 부모 프로토콜을 상속한 자식 프로토콜
protocol StudentPlayer: Student {
    var sport: String { get }
    func play()
}

// 자식 프로토콜을 채택한 구조체
struct FootballStudentPlayer: StudentPlayer {
    
    // 자식 프로토콜에 정의된 property와 method뿐만 아니라
    let sport: String
    
    func play() {
        print("\(name) is playing \(sport).")
    }
    
    // 부모 프로토콜에 정의된 property와 method도 구현해야한다.
    let name: String
    
    func study() {
        print("\(name) is studying.")
    }
}

조합 (Composition)

조합은 수평적 확장이다. typealias를 통해 구현할 수 있다.

상속과는 다르게 합쳐진 두 프로토콜은 대등한 관계이기 때문에 서로 어떤 영향도 줄 수 없다.

protocol TeaShop {
    var tea: String { get }
    func makeTea()
}

protocol CoffeeShop {
    var coffee: String { get }
    func makeCoffee()
}

// 2개의 독립된 프로토콜을 typealias를 이용해서 합친다.
typealias TeaCoffeeShop = TeaShop & CoffeeShop

struct SomeCafe: TeaCoffeeShop {
    // 2개의 프로토콜에 정의된 모든 properties
    let tea: String
    let coffee: String
    
    // 2개의 프로토콜의 정의된 모든 methods
    func makeTea() {
        print("We are making \(tea)")
    }
    
    func makeCoffee() {
        print("We are making \(coffee)")
    }
}

언제 무엇을 써야하는가?

위에 코드에서 들어져있는 예를 참고하면 언제 상속을 사용하고 언제 조합을 사용해야하는지 알 수 있다.

상속은 상위 프로토콜이 하위 프로토콜을 완전히 포함하고 있을 때 사용한다. 위의 예시에서 학생-학생 선수의 관계를 들었다. 학생 선수는 반드시 학생이다. 따라서 학생에 정의되는 모든 속성과 메소드를 가지고 있어야 한다. 이럴 때는 상속을 사용한다.

조합은 두 개의 프로토콜이 대등한 관계를 가질 때 사용한다. 찻집과 커피숍은 서로 독립된 관계이다. 따라서 한쪽에 어떤 속성이나 메소드가 추가된다고 했을 때 다른 한쪽에 영향을 끼쳐서는 안된다.

그렇다면 나는 실무의 관점에서는 어떤 것을 많이 사용하는가? 상속은 강력한 기능을 제공하지만 코드의 결합이 강하다. 이는 상속 관계가 단순한 초반에는 어렵지 않지만 상속 관계가 복잡하면 관리하기 어렵다. (심지어 어떤 개발자는 상속을 가장 잘 사용하는 방법은 상속을 사용하지 않는 것이라고 하는 것도 들었다.) 좀 더 확장성 있게 개발하려면 서로 코드의 결합이 약간 조합을 사용하는 것이 더 합리적이라고 생각한다.

따라서 나는 최대한 상속의 사용을 최소화하고 조합을 사용하려고 노력하고 있다.

마치며…

이 포스팅의 스위프트 문법은 기초적인 내용이다. 하지만 사내에 TypeScript로 개발하는 개발자와 Union Type에 대한 이야기를 나누면서 이 내용에 대해 한번 정리하면 좋겠다고 생각했다.

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.
post-custom-banner

0개의 댓글