🔥 프로토콜과 익스텐션

329자
4분

Swift에서는 protocol을 사용하여 프로토콜을 선언할 수 있습니다. 프로토콜은 특정 작업이나 기능에 적합한 메서드, 프로퍼티 등을 요구사항으로 정의합니다. 그리고 이 요구사항을 실제로 구현하는 것은 프로토콜을 채택한 타입의 역할이에요.

예를 들어, 다음과 같이 ExampleProtocol 프로토콜을 정의해 보겠습니다.

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}
swift

위 코드에서는 simpleDescription이라는 읽기 전용 프로퍼티와 adjust()라는 메서드를 요구사항으로 정의하고 있어요.

이제 클래스, 열거형, 구조체는 모두 이 프로토콜을 채택할 수 있습니다. 아래 코드를 살펴볼까요?

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
 
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
 
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
swift

SimpleClassExampleProtocol을 채택하고 있으며, 프로토콜에서 요구한 프로퍼티와 메서드를 모두 구현하고 있습니다.

이번에는 구조체에서 프로토콜을 채택하고 사용하는 예시를 살펴보겠습니다.

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
 
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
 
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
swift

구조체에서 프로토콜을 채택할 때, 구조체 내부의 프로퍼티를 변경하는 메서드 앞에는 mutating 키워드를 붙여줘야 해요. 반면에 클래스의 경우에는 이 키워드가 필요 없답니다.

또한 Swift에서는 extension을 사용하여 기존 타입에 기능을 추가할 수도 있어요. 이를 통해 메서드, 계산 프로퍼티 등을 추가로 구현할 수 있죠. 심지어 이미 존재하는 타입이 특정 프로토콜을 준수하도록 확장할 수도 있습니다.

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
 
    mutating func adjust() {
        self += 42
    }
}
 
print(7.simpleDescription)
// "The number 7" 출력
swift

위 코드에서는 Int 타입이 ExampleProtocol을 채택하도록 확장했어요. 이제 Int 타입에서도 simpleDescription 프로퍼티와 adjust() 메서드를 사용할 수 있게 되었답니다.

프로토콜은 마치 하나의 타입처럼 사용될 수도 있어요. 예를 들어, 서로 다른 타입이지만 같은 프로토콜을 준수하는 객체들의 컬렉션을 만들 수 있죠.

let protocolValue: any ExampleProtocol = a
print(protocolValue.simpleDescription)
// "A very simple class.  Now 100% adjusted." 출력
// print(protocolValue.anotherProperty)  // 주석을 제거하면 에러 발생
swift

protocolValue 변수는 ExampleProtocol 프로토콜을 준수하는 어떤 타입이든 참조할 수 있어요. 하지만 해당 프로토콜에 정의되지 않은 메서드나 프로퍼티는 사용할 수 없답니다.