(1) 프로퍼티 요구
var
키워드를 사용한 변수 프로퍼티로 정의해야 한다.static
키워드를 사용한다.(2) 메서드 요구
메서드의 이름
매개변수
반환 타입
등만 작성하며 가변 매개변수도 허용한다.static
키워드를 명시한다.static
키워드나 class
키워드 어느 쪽을 사용해도 무방하다.💡 타입으로서의 프로토콜
프로토콜은 요구만 하고 스스로 기능을 구현하지는 않는다. 그렇지만 프로토콜은 코드에서 완전한 하나의 타입으로 사용되기에 여러 위치에서 프로토콜을 타입으로 사용할 수 있다.
- 함수, 메서드, 이니셜라이저에서 매개변수 타입이나 반환 타입으로 사용될 수 있다.
- 프로퍼티, 변수, 상수 등의 타입으로 사용될 수 있다.
- 배열, 딕셔너리 등 컨테이너 요소의 타입으로 사용될 수 있다.
(3) 가변 메서드 요구
mutating
키워드를 적어 메서드에서 인스턴스 내부의 값을 변경한다.mutating
키워드를 명시해야 한다.mutating
키워드를 붙인 가변 메서드 요구
가 필요하다.(4) 이니셜라이저 요구
required
식별자를 붙인 요구 이니셜라이저로 구현해야 한다.protocol Named {
var name: String { get }
init(name: String)
}
class Person: Named {
var name: String
required init(name: String) {
self.name = name
}
}
required
와 override
식별자를 모두 명시하여 프로토콜에서 요구하는 이니셜라이저를 구현해주어야 한다. (순서는 상관없다.)class School {
var name: String
init(name: String) {
self.name = name
}
}
class MiddleSchool: School, Named {
required override init(name: String) {
super.init(name: name)
}
}
protocol ClassOnlyProtocol: class, Readable, Writable {
//추가 요구사항
}
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Age {
var name: String
var age: Int
}
class Car: Named {
var name: String
init(name: String) {
self.name = name
}
}
class Truck: Car, Aged {
var age: Int
init(name: String, age: Int) {
self.age = age
super.init(name: name)
}
}
func celebrateBirthday(to celebrator: Named & Aged) {
print("Happy birthday \(celebrator.name)!! Now you are \(celebrator.age)")
}
let yagom: Person = Person(name: "yagom", age: 90)
celebrateBirthday(to: yagom) // Happy birthday yagom!! Now you are 90
let myCar: Car = Car(name: "Boong Boong")
//celebrateBirthday(to: myCar) //Aged를 충족하지 못하므로 오류발생
//Car 클래스의 인스턴스 역할도 수행할 수 있고,
//Aged 프로토콜을 준수하는 인스턴스만 할당할 수 있다.
var someVariable: Car & Aged
//Truck 인스턴스는 Car 클래스 역할도 할 수 있고 Aged 프로토콜도 준수하므로 할당할 수 있다.
someVariable = Truck(name: "Truck", age: 5)
//Car의 인스턴스인 myCar는 Aged 프로토콜을 준수하지 않으므로 할당할 수 없다.
//오류발생!
//someVariable = myCar
print(yagom is Named) // True
print(yagom is Aged) // True
print(myCar is Named) // True
print(myCar is Aged) // False
if let castedInstance: Named = yagom as? Named {
print("\(castedInstance) is Named")
} //Person is Named
objc
속성이 부여된 프로토콜은 프로토콜의 요구사항 중 일부를 선택적 요구사항으로 지정할 수 있다.objc
속성이 부여되는 프로토콜은 Objective-C
클래스(NSObject
)를 상속받은 클래스에서만 채택할 수 있다. 즉, 열거형이나 구조체 등에서는 objc
속성이 부여된 프로토콜은 아예 채택이 불가하다.objc
속성을 사용하려면 Foundation
프레임워크 모듈을 임포트해야 한다.optional
식별자를 요구사항의 정의 앞에 붙여주면 된다.옵셔널이
된다.@objc protocol Moveable {
func walk()
@objc optional func fly()
}
class Tiger: NSObject, Moveable {
func walk() {
print("Tiger walks")
}
}
class Bird: NSObject, Moveable {
func walk() {
print("Bird walks")
}
func fly() {
print("Bird flys")
}
}
let tiger: Tiger = Tiger()
let bird: Bird = Bird()
tiger.walk()
bird.walk()
bird.fly()
var moveableInstance: Moveable = tiger
moveableInstance.fly?() //응답 없음
moveableInstance = bird
moveableInstance.fly?()
--result--
Tiger walks
Bird walks
Bird flys
Bird flys