Associated Types (관련 타입)
자 일단 공식문서 부터 보고 가시죠
When defining a protocol, it’s sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name to a type that’s used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted. Associated types are specified with the associatedtype keyword.
Associated Type은 Generic에서 나오는 개념 중 하나입니다.
하나 이상의 관련 타입을 선언할 때 유용하며, Generic과 같이 일종의 Place holder 역할을 해준다고 합니다.
즉, 진짜 타입을 주는 게 아니라 타입의 샘플을 주는 거죠. 사용할 실제 타입은 프로토콜이 채택될 때까지 지정되지 않으니 재사용성이 높아집니다.
즉, Associated Type은 일종에 프로토콜을 위한 제네릭 문법이라고 생각하면 되겠습니다.
정의
Associated Type는 타입으로 사용됩니다. 타입이므로 첫 번째 단어는 대문자가 되겠죠?
이렇게, 일단 사용되기 전까지 SomeType
은 어떠한 타입도 될 수 있습니다.
protocol SomeProtocol {
associatedtype SomeType
}
구현 예시
이렇게 만들어진 DannyProtocol
을 채택하게 되면, 반드시 age
를 String
타입으로 정의해줘야 합니다.
protocol DannyProtocol {
var age: String { get }
}
그런데 여기서 만약, 다른 타입을 사용할 여지가 있거나 사용하고 싶을 때, 사용하는 것이 바로 associatedType
입니다.
한번, 간단히 사용해 봅시다.
먼저 MyType
으로 Place holder 역할을 하는 타입을 만들어 줍니다.
associatedType
은 Place holder 역할만 할 뿐, 사용되기 전까지 값을 갖지 않는다고 했죠? 넣어주세요!
protocol DannyProtocol {
associatedtype MyType
var age: MyType { get }
}
그럼 이렇게 Associated Type을 만들어 줬고, 한번 만든 프로토콜을 사용 볼까요?
이와 같이 채택한 곳에서 원하는 타입으로 정할 수 있습니다.
struct Danny: DannyProtocol {
typealias MyType = Int
var age = 10
}
struct Danny: DannyProtocol {
typealias MyType = String
var age = "열 살"
}
또한 타입 추론으로 typealias
를 생략해 줘도 무관하죠.
하지만, 되도록이면 아래와 같이 타입은 명시적으로 나타내줍시다.
struct Danny: DannyProtocol {
var age: Int = 10
}
특징
associatedType
는 타입이라고 하였습니다.
즉, 다른 프로토콜을 채택하여 제약조건을 줄 수 있죠.
대신 사용 시 채택한 MyType
이 사용할 프로토콜을 준수하고 있어야 합니다.
예시로 Equatable
를 사용해 봅시다.
Equatable
대한 정보를 알고 싶다면 프로토콜 Equatable (타입 비교) 글을 참고해 주세요.
protocol DannyProtocol {
associatedtype MyType: Equatable
var value: MyType { get }
}
struct Danny: DannyProtocol {
var age: Int
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.age == rhs.age
}
}
let youngDanny = Danny(age: 10)
let oldDanny = Danny(age: 30)
youngDanny == oldDanny
// false
이렇게 Equatable
을 준수하는 프로토콜을 만들어 줬습니다.
예제가 조금 억지스럽긴 한데, 요점은 다른 프로토콜 채택이 가능하다.
즉, 원하는 제약 조건을 줄 수 있다는 것입니다.
Generic과 같이 활용하기
이제 구조체나 클래스와 같은 커스텀 타입에서 associatedType
을 통해 프로토콜을 채택할 때마다,
원하는 타입으로 만들어 사용할 수 있게 됐습니다.
하지만 예제와 같이 다른 타입의 인스턴스를 만들려면 구조체를 한 개 더 만들어야 하는 수고가 발생하게 됩니다...
struct DannyInt: DannyProtocol {
typealias MyType = Int
var age = 10
}
struct DannyStr: DannyProtocol {
typealias MyType = String
var age = "열 살"
}
이 때는 바로 Generic
을 활용해서 만들면 됩니다.
struct Danny<T>: DannyProtocol {
var age: T
}
위에 설명했듯이 타입을 정해주면 따로 typealias
설정은 생략할 수 있다고 했죠.
Generic은 일종에 타입의 샘플로 플레이스홀더 블라블라...
이렇게 Generic
을 활용하면 인스턴스를 생성 시 다른 타입으로 생성이 가능하게 되죠!
let dannyInt = Danny(age: 10)
let DannyStr = Danny(age: "열 살")
부족한 설명이지만, 조금은 이해 가셨나요?
틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃
'Xcode > Swift 문법' 카테고리의 다른 글
[iOS/Swift] 프로토콜 AsyncSequence (비동기 시퀀스) (0) | 2023.01.20 |
---|---|
[iOS/Swift] 프로토콜 Sequence (0) | 2023.01.19 |
[iOS/Swift] 프로토콜 Equatable (타입 비교) (0) | 2023.01.12 |
[iOS/Swift] 속성(Properties)의 종류 (0) | 2023.01.04 |
[iOS/Swift] 속성 감시자 (Observed Properties) (0) | 2023.01.04 |