[swift 기초문법] - 프로토콜 초기구현(Protocol Default Implementations), 연관타입(Associated Type)
프로토콜 초기구현이란(Protocol Default Implementations)
프로토콜의 익스텐션을 통해 구현하는 것을 프로토콜 추기구현이라고 합니다.(protocol + extension 의 결합)
프로토콜은 프로토콜을 채택하여 사용할 타입들에서 구현해줘야하는 요구사항들을 정의만 해줄 뿐 내용을 구현할 수는 없습니다.
그러나 익스텐션을 사용하면 프로토콜이 요구하는 기능을 실질적으로 정의할 수 있습니다.
다만 익스텐션에서 저장 프로퍼티는 구현이 불가능합니다.
하나의 프로토콜을 만들어 초기 구현을 해둔다면 여러 타입에서 해당 기능을 사용하고 싶을때, 프로토콜을 채택하기만 하면됩니다.
여러 부분에서 공통으로 사용되는 작업이나 기능 (시간값 가져오기 등) 의 대해서 정의하여 사용함으로써 중복 코드도 줄이고 기능의 정의 파악을 용이하게 할 수 있습니다.
이렇게 프로토콜과 익스텐션을 결합하면 코드의 재사용성이 증가합니다.
protocol SomeProtocol {
func someMethod()
}
extension SomeProtocol {
func someMethod() {
print("someMethod이 초기구현 되었다!!!")
}
}
class SomeClass: SomeProtocol {
func viewDidLoad() {
someMethod()
}
}
//초기 구현 안한 코드
protocol Talkable {
var topic: String { get set }
func talk (to: Self)
}
struct Person: Talkable {
var topic: String
var name: String
func talk(to: Person) {
print("\(topic)")
}
}
struct Monkey: Talkable {
var topic: String
func talk(to: Person) {
print("\(topic)")
}
}
//초기 구현 한 코드
protocol Talkable {
var topic: String { get set }
func talk (to: Self)
}
extension Talkable {
func talk(to: Self) {
print("\(to) : \(topic)")
}
}
struct Person: Talkable {
var topic: String
var name: String
}
struct Monkey: Talkable {
var topic: String
}
let kjy = Person(topic: "swift", name: "kjy")
let pmk = Person(topic: "swift2", name: "pmk")
kjy.talk(to: pmk)
pmk.talk(to: kjy)
프로토콜 익스텐션 기능의 재정의
프로토콜 익스텐션에서 구현되어있는 기능을 사용하지 않고 타입의 특성에 따라 재구현 하고 싶다면 아래 예제 코드와 같이 구현하시면 됩니다.
이는 오버라이드와는 다르게 동작합니다.
동작 프로세스는 준수하는 프로토콜에 이미 구현되어있다면 그 기능을 호출하고, 그렇지 않다면 초기구현의 기능을 호출하기때문입니다.
class SomeClass: SomeProtocol {
func someMethod() {
print("SomeProtocol의 someMethod를 다시 구현함!")
}
}
프로토콜 연관 타입이란(Associated Type)
연관 타입은 프로토콜에서 사용 할 수 있는 제네릭의 플레이스 홀더라고 보시면 됩니다.
protocol SomeProtocol {
associatedtype SomeType
var total: Int { get }
mutating func add(_ value: SomeType)
subscript(index: Int) -> SomeType { get }
}
class SomeClass: SomeProtocol {
var numbers: [Int] = []
var total: Int {
return numbers.count
}
func add(_ value: Int) {
numbers.append(value)
}
subscript(index: Int) -> Int {
return numbers[index]
}
}
typealias로 연간 타입의 별칭을 지정해줄 수도 있습니다.
class SomeClass: SomeProtocol {
typealias SomeType = Int
var numbers: [SomeType] = []
제네릭 타입에서는 연관 타입과 타입 매개변수를 대응시킬 수도 있습니다.
struct Test<Element>: SomeProtocol {
var items: [Element] = []
mutating func add(_ value: Element) {
#swift 기초
#swift 강의
#ios programming
'IT > Swift' 카테고리의 다른 글
[swift] Wildcard, Nested Types (0) | 2019.10.05 |
---|---|
[swift] POP (Protocol Oriented Language) (0) | 2019.09.30 |
[swift] Extension, Generic (0) | 2019.09.25 |
[swift] Type Casting (0) | 2019.09.23 |
[swift] Inheritance (0) | 2019.09.22 |