프로토콜은 인터페이스 입니다. 최소한으로 가져야할 속성이나 메서드를 정의합니다. 구현은 하지 않습니다.
protocol Sendable {
var from: String? { get }
var to: String { get }
func send()
}
클래스와 구조체에 프로토콜을 적용(Confirm)할 수 있습니다. 프로토콜을 적용하면 프로토콜에서 정의한 속성과 메서드를 모두 구현해야합니다.
protocol Sendable {
var from: String? { get }
var to: String { get }
func send()
}
struct Mail: Sendable {
var from: String?
var to: String
func send() {
print("Send a mail from \(self.from) to \(self.to)")
}
}
struct Feedback: Sendable {
var from: String? {
return nil
}
var to: String
func send() {
print("Send a feedback to \(self.to)")
}
}
프로토콜은 추상클래스처럼 사용할 수 있습니다.
func sendAnything(_ sendable: Sendable) {
sendable.send()
}
let mail = Mail(from: "dldmswo1209@gmail.com", to: "ylee886@naver.com")
sendAnything(mail)
let feedback = Feedback(to: "ylee886@naver.com")
sendAnything(feedback)
sendAnything은 Sendable 타입 파라미터를 받습니다. mail과 feedback 은 엄연히 다른 타입이지만, 모두 Sendable 프로토콜을 적용했으므로 sendAnything() 의 파라미터로 전달할 수 있습니다.
그리고 Sendable 에서는 send() 를 정의했으므로 호출 가능합니다.
프로토콜은 또 다른 프로토콜을 적용할 수 있습니다.
protocol Messagable {
var message: String? { get }
}
protocol Sendable: Messagable {
var from: String? { get }
var to: String { get }
func send()
}
Sendable은 Messagable 프로토콜을 따르는 프로토콜입니다. 따라서 Sendable 을 적용받는 구조체나 클래스에서는 message 속성을 구현해야 합니다.
Any 는 모든 타입에 대응, AnyObject 는 모든 객체에 대응합니다.
let anyNumber: Any = 10
let anyString: Any = "Hi"
let anyInstance: AnyObject = Dog()
Any 와 AnyObject 는 프로토콜입니다. Swift 에서 사용가능한 모든 타입은 Any 를 따르도록 설계되었고, 모든 클래스는 AnyObject 프로토콜이 적용되어있습니다.
anyNumber 에 10을 넣었다고 해서 Int가 아닙니다. Any 프로토콜을 따르는 어떤 값이기 때문에 Int 타입의 1과 연산을 하면, 컴파일 에러가 발생합니다.
print(anyNumber + 1) // 컴파일 에러
이럴 때에는 as 를 이용해서 다운 캐스팅 (Down Casting)을 해야합니다. Int는 Any를 따르는 타입이기 때문에 Int보다 Any의 범주가 더 크겠죠. 따라서 다운 캐스팅 입니다.
Any 는 Int뿐 아니라 다른 타입들도 포함하고 있으므로 무조건 Int 로 변환된다는 보장이 없습니다.
따라서 as? 를 사용해서 옵셔널을 취해야 합니다.
let number: Int? = anyNumber as? Int
옵셔널이기 때문에 옵셔널 바인딩을 바로 적용할 수 있겠죠.
if let number = anyNumber as? Int {
print(number + 1)
}
타입 캐스팅까지는 필요없고, 타입 검사만 하면 될 때 is 를 사용하면 됩니다.
print(anyNumber is Int) // true
print(anyNumber is String) // false
print(anyNumber is Bool) // false
print(anyNumber is Float) // false
print(anyNumber is Double) // false