제네릭 함수처럼 Swift에서는 generic type을 정의할 수 있음. 어떠한 타입에서 사용할 수 있는 커스텀 클래스, 구조체, 열거형을 만들 수 있음 Array 와 Dictionary 도 제네릭으로 구현
타입에 상관없이 사용가능한 Stack<Element> 구조체
struct Stack<Element> {
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
열거형에서 연관값에 대해서 제네릭 코드를 작성할 수 있음
enum Color<T> {
case red (T)
case green
case blue
}
확장의 경우, 타입 파라미터를 명시하지 않아도 됨 → 본체에서 정의한 타입 파라미터 적용
extension Stack {
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
where 절을 활용하여 확장을 적용할 타입 제한 가능extension Stack where Element == Int {
var squaredTopItem: Element? {
return items.isEmpty ? nil : items[items.count - 1] * items[items.count - 1]
}
}
var iStack = Stack(items: [1, 2, 3])
iStack.squaredTopItem // 9
파라미터 타입을 특정 프로토콜을 채택하는 타입 혹은 단일 클래스에 해당하는 타입에 대해서 제약 가능
Equatable 프로토콜을 채택한 타입에 대해서만 Stack 사용 가능
struct Stack<Element : Equatable> {
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
클래스 제약
특정 클래스와 상속관계에 내에 있는 클래스만 타입으로 사용할 수 있는 제약
class Person {}
class Student: Person {}
let person = Person()
let student = Student()
struct Stack<Element : Person> {
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
print("swap 완료")
}
func swapTwoValues(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
print("swap 완료 및 원소 더한 값:", a + b)
}
var a = 2
var b = 3
swapTwoValues(&a, &b)
구체적으로 타입이 명시된 함수가 실행된다!

프로토콜을 제네릭 선언 방법
associatedtype 뒤에 타입 파라미터를 명시protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
당연히 해당 타입에 대한 구체적인 명시는 프로토콜을 채택한 타입에서 작성
typealias T = Int 작성하여 실제 타입 표시 but 연관 타입이 추론이 가능하므로 생략 가능struct TV: RemoteControl {
typealias T = Int // 생략 가능
func changeChannel(to: Int) {
print("TV 채널바꿈: \(to)")
}
func alert() -> Int? {
return 1
}
}
물론 연관 타입에 대해서 제약을 걸 수 있음
protocol Container {
associatedtype Item: Equatable
}