Int, String, Double 등 다양한 타입에서 사용할 수 게 해준다.제너릭은 <T> 같은 타입 파라미터를 사용
예제
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 5
var y = 10
swapValues(&x, &y)
print(x, y) // 10, 5
<T>: 제너릭 타입을 선언
T를 사용해 어떤 타입이든 받을 수 있도록 설계
목표: Int, String 등 다양한 타입을 저장할 수 있는 스택(Stack) 만들기
struct Stack<T> { // T는 어떤 타입이든 받을 수 있는 제너릭 타입
private var elements: [T] = [] // 제너릭 타입 배열 추가
mutating func push(_ element: T) {
elements.append(element) // 배열 요소 추가
}
mutating func pop() -> T? {
return elements.popLast() // 마지막 요소 제거 후 반환
}
func peek() -> T? {
return elements.last // 마지막 요소 확인
}
}
var intStack = Stack<Int>() // Int 타입 인스턴스 생성
intStack.push(1) // 1 넣기
intStack.push(2) // 2 넣기
print(intStack.pop()) // 마지막 요소인 2 제거 후 2 출력
var stringStack = Stack<String>() // String 타입 인스턴스 생성
stringStack.push("Hello") // Hello 넣기
stringStack.push("Swift") // Swift 넣기
print(stringStack.pop()) // 마지막 요소 Swift 제거 후 "Swift" 출력
T를 활용해 Int, String 등 여러 타입에서 활용 가능목표: 두 개의 값이 같은지 비교하는 제너릭 함수 만들기
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
print(isEqual(10, 10)) // true
print(isEqual("Swift", "swift")) // false
T: Equatable 제약을 걸어 == 비교 연산을 지원하는 타입만 받도록 설정
목표: 제너릭을 활용한 Container 프로토콜 만들기
protocol Container {
associatedtype Item // 제너릭 타입 지정
mutating func add(_ item: Item)
func getAll() -> [Item]
}
struct Box<T>: Container {
var items: [T] = []
mutating func add(_ item: T) {
items.append(item)
}
func getAll() -> [T] {
return items
}
}
var intBox = Box<Int>()
intBox.add(10)
intBox.add(20)
print(intBox.getAll()) // [10, 20]
var stringBox = Box<String>()
stringBox.add("Hello")
stringBox.add("Swift")
print(stringBox.getAll()) // ["Hello", "Swift"]
associatedtype 을 사용해 프로토콜이 특정 타입을 다룰 수 있도록 구현!
Box<T>는 Container 프로토콜을 채택해 유연한 자료구조를 제공
<T>)associatedtype을 활용해 프로토콜도 제너릭화associatedtype을 활용해 프로토콜도 제너릭화 하는것을 보면서 한번 더 프로토콜의 위대함을 느꼈다.