Swift의 제네릭(Generic)은 유연하고 재사용 가능한 코드를 작성하는 데 유용합니다.
제네릭을 사용하면 타입에 관계없이 동일한 코드를 적용할 수 있습니다.
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var num1 = 10
var num2 = 20
swapValues(&num1, &num2)
print(num1, num2) // 20, 10
T는 타입 플레이스홀더이며, 함수가 호출될 때 실제 타입으로 대체됩니다.Int, String, Double 등 어떤 타입이든 사용 가능!제네릭을 사용하여 유연한 구조체(struct) 또는 클래스(class) 를 만들 수 있습니다.
struct Stack<T> {
private var elements: [T] = []
mutating func push(_ item: T) {
elements.append(item)
}
mutating func pop() -> T? {
return elements.popLast()
}
}
var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)
print(intStack.pop()) // 2
var stringStack = Stack<String>()
stringStack.push("Hello")
stringStack.push("World")
print(stringStack.pop()) // "World"
Stack<T>는 임의의 타입 T를 저장할 수 있는 자료구조Int, String 등 어떤 타입이든 동일한 로직으로 활용 가능프로토콜에서도 제네릭을 활용할 수 있습니다.
protocol Identifiable {
associatedtype ID
var id: ID { get }
}
struct User: Identifiable {
typealias ID = String
var id: String
}
struct Product: Identifiable {
typealias ID = Int
var id: Int
}
associatedtype을 사용하여 특정 타입을 유동적으로 지정 가능특정 타입에 제약 조건(Constraint) 을 걸 수 있습니다.
func compare<T: Comparable>(_ a: T, _ b: T) -> Bool {
return a > b
}
print(compare(10, 5)) // true
print(compare("apple", "banana")) // false
T: Comparable → T는 Comparable을 준수해야 함>, <, ==)을 사용 가능func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
return array.firstIndex { $0 == value }
}
print(findIndex(of: 3, in: [1, 2, 3, 4])) // 2
print(findIndex(of: "hello", in: ["swift", "hello", "world"])) // 1
T: Equatable → T는 동등 비교(==)가 가능한 타입이어야 함✔ 제네릭을 사용하면 타입에 상관없이 코드 재사용 가능
✔ 구조체, 클래스, 프로토콜에서도 활용 가능
✔ where 절을 활용하면 제약 조건을 설정할 수 있음