Tunko Development Diary

associatedtype 이란? 본문

Development/iOS 개발

associatedtype 이란?

Tunko 2022. 6. 17. 23:42

우선 associatedtype 타입은 제네릭에서 사용되는 타입입니다.

associatedtype은 연관타입이라고 불리며.

연관타입은 프로토콜의 일부분으로 타입에 플레이스홀더 이름을 부여합니다. 다시 말해 특정 타입을 지정해 사용할 수 있습니다.

연관타입의 실제 사용예시입니다.

protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
    // original IntStack implementation
    var items = [Int]()
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }
    // conformance to the Container protocol
    typealias Item = Int
    mutating func append(_ item: Int) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
}

위 코드를 하나씩 뜯어보면 Container 프로토콜을 채택한 구조체 입니다.

프로토콜에 선언한 associatedtype 인 Item에 Int 형을 할당하는것을 볼 수 있습니다.

typealias Item = Int

즉 protocol에 선언된 메서드인 mutating func append 에도 매개변수 타입이 Item 으로 되어있기에 Int로 바뀌게 됩니다.

그래서 구현부에는 mutating func append(_ item: Int) 이렇게 Int형 매개변수를 받게 됩니다.

두번째 예시

struct Stack<Element>: Container {
    // original Stack<Element> implementation
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
    // conformance to the Container protocol
    mutating func append(_ item: Element) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Element {
        return items[i]
    }
}

여기에선 Stack<Element> 를 직접적으로 선언 시 넣어주었습니다.


존재하는 타입에 연관 타입을 확장

extension Array: Container {}

이것이 가능한 이유는 Array 타입은 아래 Container에 선언된 append, count, subscript 가 모두 정의돼 있기 때문입니다.

protocol Container {
    associatedtype Item: Equatable
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

프로토콜에 연관 타입의 제한 사용하기

연관 타입을 적용할 수 있는 타입에 조건을 걸어 제한을 둘 수 있습니다.

조건을 붙일때는 where 구문을 사용합니다.

이 조건에는 특정 타입인지 여부와 특정 프로토콜을 따르는지 여부등이 사용될 수 있습니다.

다음 예시

Suffix가 SuffixableContainer 프로토콜을 따르고 item 타입이 반드시 Container의 item타입 이여야 한다는 조건을 추가 한것 입니다.

protocol SuffixableContainer: Container {
    associatedtype Suffix: SuffixableContainer where Suffix.Item == Item
    func suffix(_ size: Int) -> Suffix
}
extension Stack: SuffixableContainer {
    func suffix(_ size: Int) -> Stack {
        var result = Stack()
        for index in (count-size)..<count {
            result.append(self[index])
        }
        return result
    }
    // Inferred that Suffix is Stack.
}
var stackOfInts = Stack<Int>()
stackOfInts.append(10)
stackOfInts.append(20)
stackOfInts.append(30)
let suffix = stackOfInts.suffix(2)
// suffix contains 20 and 30

Stack 의 연관 타입인 Suffix 또한 Stack입니다.

그래서 Stack의 suffix의 실행으로 또 다른 Stack을 반환하게 됩니다.

반응형

'Development > iOS 개발' 카테고리의 다른 글

swift) lazy variables  (0) 2022.06.29
swift) ?? 연산자  (0) 2022.06.20
swift) required init 요구 이니셜라이저  (0) 2022.06.17
Swift ARC [weak self] 란?  (0) 2022.06.15
xcode 13 vim Editing Mode  (0) 2021.10.13
Comments