프로토콜 상속(protocol inheritance)
- 프로토콜은 하나 또는 그 이상의 다른 프로토콜을 상속할 수 있고, 상속한 요구사항 위에 요구사항을 더 추가할 수 있다.
protocol InheritanceProtocol : SomeProtocol, AnotherProtocol {
}
protocol PrettyTextRepresentable : TextRepresentable {
var prettyTextualDescription : String { get }
}
클래스 전용 프로토콜(Class-only-Protocol)
- 프로토콜 채택을 프로토콜의 상속 목록에 AnyObject 프로토콜을 추가해서 구조체 또는 열거형이 아닌 클래스 타입으로 제한할 수 있다.
protocol SomeClassOnlyProtocol : AnyObject, SomeInheritedProtocol {
}
- 프로토콜의 요구사항에 의해 정의된 동작이 준수하는 타입에 값이 아닌 참조체계에 의미가 있다고 보이는 경우 클래스 전용 프로토콜을 채택한다.
프로토콜의 구성
- 동시에 여러개의 프로토콜을 준수하는 타입을 요구하는게 유용할 수 있다.
protocol Named {
var name : String {get}
}
protocol Aged {
var age : Int {get}
}
struct Person : Named, Aged {
var name : String
var age : Int
}
func wishHappyBirthday(to celebrator : Named & Aged) {
print("Happy Birthday! \(celebrator.name), you're \(celebrator.age)")
let birthdayPerson = Person(name : "Malcom", age : 21)
wishHappyBirthday(to : birthdayPerson)
프로토콜 준수성 검사
- 프로토콜 준수성에 대해서 확인하고 특정 프로토콜로 캐스팅 하기 위하여 is와 as연산자를 사용할 수 있다.
- is 연산자는 인스턴스가 프로토콜을 준수한다면 true를 반환하고 그렇지 않으면 false를 반환한다.
- as?버전은 프로토콜의 타입으로 옵셔널 값을 반환하고 인스턴스가 준수하지 않는 경우 nil을 반환한다.
- as!는 준수하지 않는 경우 런타임 에러를 트리거 한다.
protocol HasArea {
var area : Double {get}
}
class Circle : HasArea {
let pi = 3.14
var radius : Double
var area : Double {return pi*radius*radius}
init(radius : Double) {
self.radius = radius
}
}
class Country : HasArea {
var area : Double
init(area : Double) {self.area = area}
}
class Animal {
var legs : Int
init(legs : Int) {self.legs = legs}
}
let objects : [AnyObject] = [Circle(radius : 2.0), Country(area : 244), Animal(legs : 4)]
for object in objects {
if let objectWithArea = object as? HasArea {
print("Area is \(objectWithArea.area)")
} else {
print("Something that doesn't have an Area")
}
}