본문 바로가기
개발서적 읽으며 끄적끄적/POP with Swift

프로토콜 확장으로 기능을 추가하기

by 토끼찌짐 2020. 1. 1.

존 호프만의 Protocol-Oriented Programming with Swift(스위프트 프로토콜지향 프로그래밍) 5장 읽으며 메모 (요약글 아님)


프로토콜 확장의 이점

(기능을 추가로 지원해주는 관점에서, 서브클래싱으로 그것을 이루었을 때와 비교했을 때)

클래스를 서브클래싱하여 그곳에 원하는 기능을 더했을 때의 한계: 원본 클래스에는 실제 기능을 추가하지 않으므로, 그 기능이 필요한 부분에서는 원본 클래스의 모든 인스턴스를 새로운 서브클래스의 인스턴스로 변경해야 한다.

프로토콜 확장의 경우, 해당 프로토콜을 따르기만 하면 그 기능을 제공할 수 있기 때문에 이런 치환 작업 없이 자동으로 확장한 함수/프로퍼티를 이용할 수 있다.

물론, 서브클래싱은 참조 타입(클래스 등)만 가능하고 값 타입(구조체, ENUM 등)에는 불가하다는 한계도 있다. 프로토콜의 경우에는 참조 타입과 값 타입에 모두 적용 가능하다.

 

프로토콜 확장을 이럴 때 쓰면 좋다

저자의 예시(정규식 프로토콜)는 좀 어려워서, 저자가 말하고자 하는 바를 설명할 수 있는 간단한 예제를 새로 만들어보았다.

// as-is
protocol Circle {
    var radius: Double { get }          // 반지름
    var area: Double { get }            // 넓이
    var circumference: Double { get }   // 둘레
}

struct MyCircle: Circle {

    let radius: Double

    var area: Double {
        return self.radius * self.radius * Double.pi
    }

    var circumference: Double {
        return self.radius * 2 * Double.pi
    }
}

let myCircle = MyCircle(radius: 4.0)
myCircle.area // 50.26..
myCircle.circumference // 25.13..


//to-be
protocol Circle {
    var radius: Double { get }
}

extension Circle {
    // 프로토콜 확장을 통해 넓이와 둘레를 프로토콜에서 제공해줄 수 있다
    var area: Double {
        return self.radius * self.radius * Double.pi
    }

    var circumference: Double {
        return self.radius * 2 * Double.pi
    }
}

struct MyCircle: Circle {

    let radius: Double
}

let myCircle = MyCircle(radius: 4.0)
myCircle.area // 50.26..
myCircle.circumference // 25.13..