🔥 프로토콜과 익스텐션
Swift에서는 protocol을 사용하여 프로토콜을 선언할 수 있습니다. 프로토콜은 특정 작업이나 기능에 적합한 메서드, 프로퍼티 등을 요구사항으로 정의합니다. 그리고 이 요구사항을 실제로 구현하는 것은 프로토콜을 채택한 타입의 역할이에요.
예를 들어, 다음과 같이 ExampleProtocol 프로토콜을 정의해 보겠습니다.
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}위 코드에서는 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.simpleDescriptionclass 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.simpleDescriptionSimpleClass는 ExampleProtocol을 채택하고 있으며, 프로토콜에서 요구한 프로퍼티와 메서드를 모두 구현하고 있습니다.
이번에는 구조체에서 프로토콜을 채택하고 사용하는 예시를 살펴보겠습니다.
struct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescriptionstruct SimpleStructure: ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription구조체에서 프로토콜을 채택할 때, 구조체 내부의 프로퍼티를 변경하는 메서드 앞에는 mutating 키워드를 붙여줘야 해요. 반면에 클래스의 경우에는 이 키워드가 필요 없답니다.
또한 Swift에서는 extension을 사용하여 기존 타입에 기능을 추가할 수도 있어요. 이를 통해 메서드, 계산 프로퍼티 등을 추가로 구현할 수 있죠. 심지어 이미 존재하는 타입이 특정 프로토콜을 준수하도록 확장할 수도 있습니다.
extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
// "The number 7" 출력extension Int: ExampleProtocol {
var simpleDescription: String {
return "The number \(self)"
}
mutating func adjust() {
self += 42
}
}
print(7.simpleDescription)
// "The number 7" 출력위 코드에서는 Int 타입이 ExampleProtocol을 채택하도록 확장했어요. 이제 Int 타입에서도 simpleDescription 프로퍼티와 adjust() 메서드를 사용할 수 있게 되었답니다.
프로토콜은 마치 하나의 타입처럼 사용될 수도 있어요. 예를 들어, 서로 다른 타입이지만 같은 프로토콜을 준수하는 객체들의 컬렉션을 만들 수 있죠.
let protocolValue: any ExampleProtocol = a
print(protocolValue.simpleDescription)
// "A very simple class. Now 100% adjusted." 출력
// print(protocolValue.anotherProperty) // 주석을 제거하면 에러 발생let protocolValue: any ExampleProtocol = a
print(protocolValue.simpleDescription)
// "A very simple class. Now 100% adjusted." 출력
// print(protocolValue.anotherProperty) // 주석을 제거하면 에러 발생protocolValue 변수는 ExampleProtocol 프로토콜을 준수하는 어떤 타입이든 참조할 수 있어요. 하지만 해당 프로토콜에 정의되지 않은 메서드나 프로퍼티는 사용할 수 없답니다.










