ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • associatedType
    Swift 2020. 3. 18. 16:52

    오늘은 associatedType 에 대해 알아보겠습니다!

    associatedType을 이해하기 위해서는 Protocol 과 Generic 에 대해 먼저 이해하고 계셔야합니다. 

    왜냐하면 associatedType 은 Protocol을 위한 Generic 이라고 생각하시면 되기 때문이죠. 🙃

     


     

    정의

    공식 문서에서는 다음과 같이 설명하고 있어요.

    An associated type gives a placeholder name to a type that is used as part of the protocol. The actual type to use for that associated type isn’t specified until the protocol is adopted.

    associated type 은 protocol 에서 사용될 임의의 타입이름을 주는 것이라고 하네요. 프로토콜을 정의하면 그제서야 실제 타입이 정의된다는 말이에요. 제네릭과 개념적으로는 똑같죠??

     

    구현

    이제 실제로 어떻게 사용되는지 볼까요?

     

    protocol 정의

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

    Container protocol에서 Item이라는 타입을 만들어 사용하고 있어요. 아직 Item이 어떤 타입이 될 지는 모르는 상태죠.

    타입이 지정될 때 가지는 Item 이라는 임의의 타입 알고 있겠다는 의미에요.

    이제 이 protocol을 정의할 때는 typealias나 generic을 사용해 Item의 타입을 지정해줄 수 있습니다.

     

    non generic struct

    이제 이 Container를 상속받은 struct를 하나 만들어볼까요?

    struct NonGenericIntStack: Container {
    
    }

    이렇게 하면

    Type 'NonGenericStack' does not conform to protocol 'Container' 

    이라고 뜨면서 protocol을 준수하지 않았다고 하네요. Fix를 해보면!

    struct NonGenericIntStack: Container {
        typealias Item = <#type#>
        
        
    }

    이렇게 typealias Item 을 통해서 Item의 타입을 먼저 지정하라고 알려줍니다.

    Item의 타입을 Int로 지정하고 다시 Fix 를 통해 나머지 Container protocol을 준수해서 자동완성을 시켜보면

    struct NonGenericIntStack: Container {
        typealias Item = Int
        
        func append(_ item: Int) {
            
        }
        
        var count: Int
        
        subscript(i: Int) -> Int {
            
        }
    }

    다음과 같이 Item이 사용되었던 부분이 지정한 Int 타입이 들어가서 자동완성이 됩니다. 
    이때 typealias 없이 Item 부분을 Int와 같은 특정 타입으로 지정해줘도 

    물론 Item의 명확히 해줬다면 Int 대신 Item을 사용해도 되겠죠?

    struct NonGenericIntStack: Container {
        typealias Item = Int
        
        func append(_ item: Item) {
            
        }
        
        var count: Int
        
        subscript(i: Int) -> Item {
            
        }
    }

    이렇게 generic 없이 struct를 만들어 사용할 수 있습니다.

    struct NonGenericStack: Container {
        typealias Item = Int
    
        var items = [Item]()
    
        mutating func append(_ item: Item) {
            self.items.append(item)
        }
    
        var count: Int {
            return items.count
        }
    
        subscript(i: Int) -> Item {
            return items[i]
        }
    }
    
    func main() {
        var stack = NonGenericIntStack()
        stack.append(10)
    }

    이때 typealias를 사용하지 않고 Item 자리에 Int 같은 특정 타입을 바로 지정해줘도 오류는 나지 않지만 
    프로토콜을 준수해주는게 좋겠죠??!!

    generic struct

    이번엔 generic을 사용해서 struct를 만들어 볼게요. 

    한번 해보셨으니 감 잡으셨죠?? 간략하게 결과만 보고 비교해보면 될 것 같아요. 

    struct GenericStack<Element>: Container {
        
        var items = [Element]()
    
        mutating func append(_ item: Element) {
            self.items.append(item)
        }
    
        var count: Int {
            return items.count
        }
    
        subscript(i: Int) -> Element {
            return items[i]
        }
    }
    
    func main() {
        var stack = GenericStack<Int>()
        stack.append(10)
    }

    이렇게 Generic 타입의 struct를 정의하면 typealias 없이 사용할 수 있답니다.


    여기에 덧붙여 associatedType에도 Equatable 이나 특정 타입만 정의하도록 제한을 둘 수도 있답니다.

    추가적인 내용은 다음에 다뤄보도록 할게요.

    자세한 내용은 역시 공식 도큐먼트가 짱이겠죠? 

     

    감사합니다 :)

     

     

    'Swift' 카테고리의 다른 글

    ~= 연산자 in Swift  (0) 2020.07.07
    Hashable in Swift 5  (0) 2020.06.25
    @discardableResult  (0) 2020.03.18
    ARC(Autometic Reference Counting)  (0) 2020.02.03
    escaping closure  (0) 2020.01.30

    댓글

Designed by Tistory.