제네릭은 함수나 타입에서 아직은 필요한 타입을 알지 못한다. 지금은 플레이스 홀더를 제공하고 실행해야 하는 타입에 대해서는 런타입에 알려주도록 하는 것.
제네릭을 사용하면 정의한 요구 사항에 따라 모든 유형에서 작동할 수 있는 유연하고 재사용 가능한 함수 및 유형을 작성할 수 있습니다. 중복을 피하고 명확하고 추상적인 방식으로 의도를 표현하는 코드를 작성할 수 있습니다.
https://docs.swift.org/swift-book/LanguageGuide/Generics.html
// Int
func swapTwoInts(a: inout Int, b: inout Int){
let tmp = a
a = b
b = tmp
}
// Double
func swapTwoDoubles(a: inout Double, b: inout Double){
let tmp = a
a = b
b = tmp
}
// String
func swapTwoStrings(a: inout String, b: inout String){
let tmp = a
a = b
b = tmp
}
👎 타입에 따라 매번 함수를 새로 만들어야한다.
👎 함수 간의 유일한 차이점은 매개변수 타입뿐이기 때문에 함수들은 중복 코드를 갖게 된다.
func swapTwoValues<T>(a: inout T, b: inout T){
let tmp = a
a = b
b = tmp
}
사용 예제
// 사용 예제 (Int)
var a = 5
var b = 10
swapTwoValues(a: &a, b: &b)
print("a: \(a), b: \(b)") // "a: 10, b: 5"
// 사용 예제 (String)
var a = "hello"
var b = "juh2"
swapTwoValues(a: &a, b: &b)
print("a: \(a), b: \(b)") // "a: juh2, b: hello"
👍 타입에 따라 매번 함수를 새로 만들지 않아도 된다.
👍 중복 코드 제거
var a = 5
var b = "hello"
swapTwoValues(a: &a, b: &b) // ❌
첫번째 매개변수가 Integer 타입의 인스턴스이기 때문에 함수안에 T로 정의된 제네릭 타입은 모두 Interger 타입이 된다.
제네릭 타입은 반드시 구체적인 클래스를 상속하거나 특정 프로토콜을 따라야 한다고 명시한다.
//Comparable 프로토콜을 따르는 타입만 T자리에 들어올 수 있음
func testGenericComparable<T: Comparable>(a: T, b: T) -> Bool {
return a == b
}