- Total
꿈꾸는리버리
protocol 정복기 ( 3 / 3) 본문
이전포스팅에서 protocol에서 method나 init을 요구할 때에 대해 알아봤다.
이번 포스팅에서는 프로토콜을 상속하는 경우, class 전용 프로토콜, 그리고 프로토콜의 조합과 프로토콜을 준수했는지 확인하는 등...의 프로토콜의 또 다른 부분을 다뤄보고자 한다.
🌷 protocol의 상속
protocol은 하나 이상의 protocol을 상속 받아 기존 protocol의 요구사항보다 더 많은 요구사항을 추가할 수 있다. 클래스의 상속 문법과 유사하기 때문에 크게 어렵지는 않다 !
protocol FirstProtocol {
var name: String { get }
}
protocol FirstProtocol2 {
var height: Int { get }
}
protocol SecondProtocol: FirstProtocol, FirstProtocol2 {
var age: Int { get }
}
class someClass: SecondProtocol {
var name: String
var height: Int
var age: Int
init() {
self.name = "River"
self.height = 200
self.age = 200
}
}
이렇게 FirstProtocol과 FirstProtocol2를 상속 받은 SecondProtocol이 있고, someClass는 SecondProtocol을 따르기 때문에 3개의 protocol에서 요구하는 사항을 모두 준수해야 한다.
🌷 클래스 전용 protocol
이렇게 protocol의 상속 리스트에 AnyObject 키워드를 추가하면 프로토콜이 클래스 타입에만 채택될 수 있도록 제한할 수 있다. (프로토콜의 상속 리스트 중 맨 처음에 위치해야 함)
protocol SomeProtocol: AnyObject {
var name: String { get }
}
class someClass: SomeProtocol {
var name: String
init() {
self.name = "River"
}
}
기존에는 AnyObject 대신에 class를 적었었는데 Swift 4 이후로는 AnyObject를 작성한다고 한다. (참고)
🌷 protocol 조합
하나의 매개변수가 여러 프로토콜을 준수하는 타입이어야 한다면, & 을 사용해서 하나의 매개변수에 여러 프로토콜을 한번에 조합하여 요구할 수 있다.
protocol SomeProtocol: AnyObject {
var name: String { get }
}
protocol SomeProtocol2: AnyObject {
var age: Int { get }
}
func someFunc(parameter: SomeProtocol & SomeProtocol2) {
// do something
}
이와 함께 특정 클래스의 인스턴스 역할을 할 수 있는지도 함께 확인할 수 있는데, 조합 중에 클래스는 한 타입만 조합할 수 있다. ( struct와 enum은 불가 )
class someClass {
var name: String = ""
var age: Int = 0
}
func someFunc(parameter: SomeProtocol & SomeProtocol2 & someClass) {
// do something
}
🌷 protocol 준수 확인
is 연산자를 통해 해당 인스턴스가 특정 프로토콜을 준수하는지 확인할 수 있다.
protocol SomeProtocol {
var name: String { get }
}
protocol SomeProtocol2 {
var age: Int { get }
}
class SomeClass: SomeProtocol, SomeProtocol2 {
var name: String = ""
var age: Int = 0
}
let someclass: SomeClass = SomeClass()
print(someclass is SomeProtocol)
as? 다운 캐스팅 연산자를 통해 다른 프로토콜로 다운캐스팅을 시도해볼 수 있다.
protocol SomeProtocol {
var name: String { get }
}
protocol SomeProtocol2 {
var age: Int { get }
}
class SomeClass: SomeProtocol, SomeProtocol2 {
var name: String = ""
var age: Int = 0
}
let someclass: SomeClass = SomeClass()
if let someProtocol2: SomeProtocol2 = someclass as? SomeProtocol2 {
print("\(someProtocol2) is SomeProtocol2")
}
요론거는 언제 쓰나면,,
이렇게 someClass는 SomProtocol의 타입이기 때문에 someProtocol의 요구 method와 property만 사용할 수 있지만,
다운 캐스팅을 하면 인스턴스 자체의 method와 property를 사용할 수 있다.
protocol의 장점
자세한 Type을 숨길 수 있다! student인지, teacher인지에 상관 없이 person이기만 하면 되는 것처럼 개발자는 구체적인 Type에 일일히 대응하거나 특정 구조체(Type)를 return하는 경우들 하나하나에 연연하지 않을 수 있다. 이렇게 Protocol에 호환되도록 하고, 그 Protocol에 맞춰서 코드를 작성한다면 protocol을 위반하지 않는 선에서 특정 구조체 내부에 변화가 있더라도 모든 코드의 의존성이 깨질까 걱정하지 않아도 된다! 이런 이유 때문에 Test를 할 때 protocol을 사용하게 된다.
또, Protocol은 Type이기 때문에 활용할 수 있는 범위가 넓다. 함수의 매개변수로 사용되기도 하고, 리턴값으로 사용되기도 하는 등 활용할 수 있는 가능성이 매우 높다.
마지막으로는 class와 달리 다중 상속이 가능하다는 점이다! 한 Protocol이 다른 Protocol을 여러개 채택할 수도 있고, 한 구조체나 클래스가 많은 Protocol을 채택할 수 있기 때문에 활용도가 높다.
참조
https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
'오뚝이 개발자 > swift' 카테고리의 다른 글
DateFormatter extension으로 관리하기 (0) | 2022.07.25 |
---|---|
delegate란? (protocol을 곁들인..) (1/2) (0) | 2022.07.24 |
protocol 정복기 ( 2/ 3) (0) | 2022.07.24 |
protocol 정복기 ( 1 / 3) (0) | 2022.07.24 |
Class 안의 Struct와 Struct 안의 Class ! (0) | 2022.07.14 |