Swift Generic

Jee.e (황지희)·2022년 4월 13일
0
post-custom-banner

Generic

  • 타입에 의존하지 않는 범용 코드를 작성할 때 사용
  • 중복을 피하고, 코드를 유연하게 작성할 수 있다.
  • Array / Dictionary 도 제네릭 타입이다.
  • swift에게 <>를 사용함으로써, “T는 새로운 타입이 아니야! 이 타입이 존재하는지 찾지마” 라고 말해주는 것
  • <> 내부에는 타입 매개변수 이름을 지정해줄 수 있는데, 제네릭 함수와 타입 매개변수와의 관계를 더 명확하게 표현해 줄 수 있는 이름을 넣는다.
  • 특별히 관계의 의미를 표현하기 어려울 때는, 관용적으로 T / U / V 등 대문자 한글자로 표현한다.

✅ 제네릭 타입
제네릭 타입을 구현하면 구조체, 클래스, 열거형 등이 어떤 타입과도 연관되어 동작한다. (Array / Dictionary가 모든 타입을 요소로 삼을 수 있는 이유)

아래의 예시를 보면 Element 를 제네릭으로 선언해주어, 그 안에 모든 타입을 넣을 수 있는걸 확인할 수 있다.

struct Stack<Element> {
    var items = [Element]()
    
    mutating func push(item: Element) {
        items.append(item)
    }
    
    mutating func pop() -> Element {
        return items.removeLast()
    }
    
}

var doubleStack = Stack<Double>()
doubleStack.push(item: 1.0)
doubleStack.push(item: 2.0)
print(doubleStack.items) // [1.0, 2.0]

doubleStack.pop() // [1.0]

var strStack = Stack<String>()
strStack.push(item: "123")
strStack.push(item: "456")
print(strStack.items) // ["123", "456"]

var anyStack = Stack<Any>()
anyStack.push(item: "여기엔 아무거나 들어올 수 있어요")
anyStack.push(item: 1.2)
anyStack.push(item: 10)
anyStack.push(item: "이렇게")
print(anyStack.items) // ["여기엔 아무거나 들어올 수 있어요", 1.2, 10, "이렇게"]

✅ 타입 제약

  • 제네릭은 타입 제약 없이 사용되지만, 가끔 제네릭 함수가 처리해야 할 기능이 특정 타입에만 한정되어야 할 때가 있다. (혹은 특정 프로토콜을 따르는 타입만 사용하도록 하거나)
  • 예를들어 Dictionary는 Hashable 프로토콜을 준수하는 타입만 사용 가능하다.
  • 아래와 같이 명시하면, 해당 타입에서만 사용이 가능하다.
  • 타입제약은 클래스 혹은 프로토콜만 가능
struct Stack<Element: Int> {
    var items = [Element]()
    
    mutating func push(item: Element) {
        items.append(item)
    }
    
    mutating func pop() -> Element {
        return items.removeLast()
    }
    
}

✅ 프로토콜 연관 타입(AssociatedType)

  • 연관타입은 프로토콜에서 사용할 수 있는 플레이스 홀더 타입니다.
  • 제네릭에서는 종류는 알 수 없으나, 어떤 타입이 여기 쓰일것이다 라고 표현해주는 것
 protocol Container {
     associatedtype ItemType
     // 존재하지 않는 타입인 ItemType 를 연관타입으로 정의해 프로토콜 정의 시 타입 이름으로 사용함
     var count: Int {get}
     mutating func append(_ item: ItemType)
     subscript(_ index: Int) -> ItemType {get}
 }
 
 // ItemType 대신 실제 타입인 Int로 구현
 class MyContainer: Container {
     var items = [Int]()
     
     var count: Int {
         return items.count
     }
     
     func append(_ item: Int) {
         items.append(item)
         
         subscript(index: Int) -> Int {
             return items[i]
         }
     }
 }
profile
교훈없는 경험은 없다고 생각하는 2년차 iOS 개발자입니다.
post-custom-banner

0개의 댓글