intro) Generic Type

제네릭 타입이란

타입에 의존하지 않는 범용 코드를 작성할 때 사용한다

제네릭을 사용하면 중복을 피하고, 코드를 유연하게 작성할 수 있다

struct Stack<T: Equatable> {
    func push(value: T) { }
    func pop() -> T { ... }
}

1. Associated Type

1-1. protocol에서도 제네릭을 사용하고 싶다면?

똑같이 타입 파라미터를 통해서 하면… 어? 왜 안되지?

프로토콜에서 제네릭 타입을 사용하고 싶으면 Associated Type을 활용해야 한다!

protocol Stack<T: Equatable> { // error! An associated type named 'T' must be declared in the protocol 'Stack' or a protocol it inherits
    func push(value: T)
    func pop() -> T
}

1-2. associatedtype?

Protocol에서 Generic을 사용하는 방법

  1. 제네릭 타입으로 사용하고 싶은 타입을 → associatedtype으로 선언한다
  2. 제네릭 타입을 사용할 곳에 해당 타입을 넣어주면 된다.
  3. 당연히 제네릭에 제한을 걸 수도 있다!
protocol Stack {
    associatedtype value
		associatedtype value2: Equatable // 이런식으로 제네릭 타입에 제약을 줄 수 잇다!
    
    func push(value: value)
    func pop() -> value
}

1-3 . 채택한 곳에서 사용하기

제네릭의 특징은 실제 사용하는 곳에서 타입이 정해지는 것이다. 그걸 표현하는 두가지 방법이 있다.

  1. typealias를 통해 associatedtype을 어떤 타입으로 사용할지 정해준다
  2. 타입 추론을 할 수 있도록 하고 typealias를 생략한다
// --- 1
struct VStack: Stack {
    typealias value = Int
    
    func push(value: value) { }
    func pop() -> value { ... }
}

// --- 2
struct VStack: Stack {
    func push(value: Int) { }
    func pop() -> Int { ... }
}