제네릭
타입에 의존하지 않는 범용 코드를 작성할 때 사용
제네릭 방법으로 코드를 작성하는 경우
같은 내용의 함수를 오버로딩할 필요 없이 한 번만 작성하여 사용할 수 있다.
제네릭 타입
제네릭은 함수뿐만 아니라 구조체, 클래스, 열거형 타입에도 선언하여 사용할 수 있다.
제네릭을 선언할 때 <>를 사용하여 선언한다.
제네릭을 이미 우리는 알게 모르게 사용했었다..!
let array: Array<Int> = .init()
swift에서는 배열이 바로 제네릭으로 구현되어 있다!
타입 제약
프로토콜 제약
만약 매개변수 2개를 받아서 반환하는 함수를 만들었을 때
func isSameValues<T>(_ a: T, _ b: T) -> Bool {
return a == b
}
해당 함수는 오류를 발생시킨다. → 반환할 때 '=='연산자는 Equatable이라는 프로토콜을 준수해야 사용할 수 있는데 아닐 수도 있는 가능성이 있으므로 오류 발생
따라서 해당 기능을 사용하고 싶은 경우
func isSameValues<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
T에 Equatable이라는 제약을 줘서 사용할 수 있다.
클래스 제약
클래스 제약 같은 경우에도 프로토콜 제약과 유사하지만
class Bird{}
class Human{}
class Teacher: Human {}
func printName<T: Human>(_ a: T) {}
let bird = Bird.init()
let human = Human.init()
let teacher = Teacher.init()
printName(bird) //오류 발생
printName(human)
printName(teacher)
제네릭에 제약이 부여된 경우 해당 클래스와 연관이 없는 클래스는 사용할 수 없다.
제네릭 확장
제네릭으로 구성되어 있는 Array, Class 등을 확장하여 사용할 때 함수 내부를 변경할 수 없지만 where을 이용하여 제약을 부여할 수 있다.
extension Array where Element: FixedWidthInteger {
mutating func pop() -> Element { return self.removeLast() }
}
위와 같이 where을 이용해 제약을 부여하게 되면 FixedWidthInteger라는 프로토콜을 준수해라 라는 의미이다.
제네릭 함수와 오버로딩
func swapValues<T>(_ a: inout T, _ b: inout T) {
print("generic func")
let tempA = a
a = b
b = tempA
}
func swapValues(_ a: inout Int, _ b: inout Int) {
print("specialized func")
let tempA = a
a = b
b = tempA
}
위와 같이 swapValues라는 제네릭 함수를 오버로딩하여 직접적인 타입을 부여한 후 다른 함수로 변경하여 사용할 수 있다.
(직접적으로 타입을 지정한 함수가 우선순위가 높기 때문!)
# 참고한 사이트
'iOS > 문법' 카테고리의 다른 글
Swift 문법과 친해지기 - ARC(Automatic Reference Counting) (0) | 2023.01.07 |
---|---|
Swift 문법과 친해지기 - 패턴 (0) | 2023.01.06 |
Swift 문법과 친해지기 - protocol (0) | 2023.01.04 |
Swift 문법과 친해지기 - Type Casting 와 Any, AnyObject (0) | 2023.01.04 |
Swift 문법과 친해지기 - Subscript (0) | 2022.12.31 |