🔥 프로토콜 확장

473자
6분

프로토콜은 준수하는 타입에 메서드, 이니셜라이저, 서브스크립트 및 계산 속성 구현을 제공하도록 확장될 수 있습니다. 이를 통해 각 타입의 개별 준수 또는 전역 함수에서가 아니라 프로토콜 자체에 대한 동작을 정의할 수 있습니다.

예를 들어, RandomNumberGenerator 프로토콜은 필수 random() 메서드의 결과를 사용하여 임의의 Bool 값을 반환하는 randomBool() 메서드를 제공하도록 확장할 수 있습니다:

extension RandomNumberGenerator {
    func randomBool() -> Bool {
        return random() > 0.5 // random() 결과가 0.5보다 크면 true를, 그렇지 않으면 false를 반환합니다.
    }
}
swift

프로토콜에 확장을 생성함으로써 모든 준수 유형은 추가 수정 없이 자동으로 이 메서드 구현을 얻습니다.

let generator = LinearCongruentialGenerator() // LinearCongruentialGenerator 인스턴스를 생성합니다.
print("Here's a random number: \(generator.random())")
// "Here's a random number: 0.3746499199817101"이 출력됩니다.
print("And here's a random Boolean: \(generator.randomBool())")
// "And here's a random Boolean: true"가 출력됩니다.
swift

프로토콜 확장은 준수 유형에 구현을 추가할 수 있지만 프로토콜이 다른 프로토콜에서 확장되거나 상속되도록 할 수는 없습니다. 프로토콜 상속은 항상 프로토콜 선언 자체에 지정됩니다.

기본 구현 제공(Providing Default Implementations)

프로토콜 확장을 사용하여 해당 프로토콜의 모든 메서드 또는 계산된 속성 요구 사항에 대한 기본 구현을 제공할 수 있습니다. 준수 유형이 필수 메서드 또는 속성에 대한 자체 구현을 제공하는 경우 확장에서 제공하는 구현 대신 사용됩니다.

예를 들어, TextRepresentable 프로토콜을 상속하는 PrettyTextRepresentable 프로토콜은 textualDescription 속성에 액세스한 결과를 반환하도록 필수 prettyTextualDescription 속성에 대한 기본 구현을 제공할 수 있습니다:

extension PrettyTextRepresentable {
    var prettyTextualDescription: String {
        return textualDescription // textualDescription 속성의 값을 반환합니다.
    }
}
swift

프로토콜 확장에 제약 조건 추가(Adding Constraints to Protocol Extensions)

프로토콜 확장을 정의할 때 확장의 메서드와 속성을 사용할 수 있기 전에 준수 유형이 충족해야 하는 제약 조건을 지정할 수 있습니다. 제네릭 where 절을 작성하여 확장하는 프로토콜 이름 뒤에 이러한 제약 조건을 작성합니다. 일반 where 절에 대한 자세한 내용은 제네릭 Where 절을 참조하세요.

예를 들어, 요소가 Equatable 프로토콜을 준수하는 모든 컬렉션에 적용되는 Collection 프로토콜에 대한 확장을 정의할 수 있습니다. 컬렉션의 요소를 Equatable 프로토콜(Swift 표준 라이브러리의 일부)로 제한함으로써 ==!= 연산자를 사용하여 두 요소 간의 동등성과 불평등을 확인할 수 있습니다.

extension Collection where Element: Equatable {
    func allEqual() -> Bool {
        for element in self {
            if element != self.first { // 첫 번째 요소와 현재 요소가 같지 않으면 false를 반환합니다.
                return false
            }
        }
        return true // 모든 요소가 같으면 true를 반환합니다.
    }
}
swift

allEqual() 메서드는 컬렉션의 모든 요소가 동일한 경우에만 true를 반환합니다.

모든 요소가 동일한 정수 배열과 그렇지 않은 정수 배열 두 개를 고려해 보겠습니다:

let equalNumbers = [100, 100, 100, 100, 100] // 모든 요소가 같은 배열
let differentNumbers = [100, 100, 200, 100, 200] // 요소가 다른 배열
swift

배열은 Collection을 준수하고 정수는 Equatable을 준수하므로 equalNumbersdifferentNumbersallEqual() 메서드를 사용할 수 있습니다:

print(equalNumbers.allEqual())
// "true"가 출력됩니다.
print(differentNumbers.allEqual())
// "false"가 출력됩니다.
swift

프로토콜 확장을 통해 프로토콜에 기본 구현을 제공하고, 제약 조건을 추가하여 메서드와 속성의 사용 범위를 제한할 수 있습니다. 이를 활용하면 더욱 유연하고 재사용 가능한 코드를 작성할 수 있겠죠? 프로토콜 지향 프로그래밍(Protocol-Oriented Programming)의 강력함을 느낄 수 있습니다.