제네릭
제네릭은 유연하고 재사용 가능한 함수와 타입의 코드를 작성하는 것을 가능하게 해 줌.
→ 중복을 피할 수 있습니다!
사실 우리가 사용하는 것들중 많은 것들이 제네릭으로 되어 있는데 대표적으로 배열, 딕셔너리가 있음!
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \\(someInt), and anotherInt is now \\(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temporaryA = a
a = b
b = temporaryA
}
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temporaryA = a
a = b
b = temporaryA
}
위 예제에서 각 함수를 주목하자!
파라미터들의 타입만 다르고 함수의 내용은 동일함!!!
이러한 경우에 제네릭을 사용해 동일한 기능을 수행하는 하나의 함수로 만들 수 있음!!!!!!!!!
제네릭 함수(Generic Functions)
위 예제에 있는 세 함수를 제네릭 함수로 만들어 보겠음!
함수명 뒤에 플레이스 홀더인 <T> 을 선언하고 파라미터를 T 타입으로 선언
이는 어떤 타입인지는 명시하지 않지만, 인자의 타입이 동일함을 알려줌.
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
swapTwoValues 함수가 실행되면 T에 해당하는 값을 함수에 넘김!
func swapTwoInts(_ a: inout Int, _ b: inout Int)
func swapTwoValues<T>(_ a: inout T, _ b: inout T)
다음과 같이 정상적으로 실행됨을 확인할 수 있다.
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt is now 107, and anotherInt is now 3
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
// someString is now "world", and anotherString is now "hello"
Type Parameters, 타입 파라미터
- 위에서 사용한 T는 타입 파라미터의 예임.
- 함수명 바로 뒤에 작성하며 꺽쇄로 묶어 사용한다.
- 복수의 타입 파라미터는 콤마를 이용해서 구분해 사용할 수 있음.
Naming Type Parameters, 파라미터 이름 짓기
- element간 상관관계가 있을 경우 의미가 있는 이름을 붙힘
- 그 외에는 T, U, V 등 단일 문자로 파라미터 이름을 작성!
Generic Types, 제네릭 타입
- 제네릭은 함수이외에도 구조체, 클래스, 열거형 타입에도 선언이 가능하다!
Extending a Generic Type, 제네릭 타입의 확장
- 익스텐션을 이용해 제네릭 타입의 확장이 가능
Type Constraints, 타입 제한
- 제네릭 함수를 선언할 때, 파라미터 뒤에 상속 받아야 하는 클래스를 선언하거나
- 반드시 따라야 하는 프로토콜을 명시할 수 있음
// 두 파라미터의 값이 같으면 true, 다르면 false를 반환하는 함수
func isSameValues<T>(_ a: T, _ b: T) -> Bool {
return a == b
// Binary operator '==' cannot be applied to two 'T' operands
}
위와 같은 함수가 있다고 가정해 봅시다.
틀린게 없어 보이는 데 주석 처리한 오류가 발생합니다!! 왜 날까여?
== 연산자는 파라미터의 타입이 Equatable이란 프로토콜을 준수할 때만 사용할 수 있기 때문입니다!!!!
위에서는 타입 파라미터를 T라는 제네릭 타입을 사용했기 때문에 해당 파라미터가 Equatable 프로토콜을 준수하는지 알 수 없기 때문입니다!!!!!!!
이 때!!!! 다음과 같이 해당 프로토콜을 준수하라고 제약을 줄 수 있음.
func isSameValues<T: Equatable>(_ a: T, _ b: T) -> Bool {...
Generic Overloading
지금까지 본 제네릭은 모든 타입이 될 수 있음!!
근데 제네릭 타입이 아닌 특정 타입으로 동작하는 함수를 만들고 싶으면 오버로딩하면됨!!
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
}
var a = 1
var b = 2
swapValues(&a, &b) //"specialized func"
var c = "Hi"
var d = "Sodeul!"
swapValues(&c, &d) //"generic func"
swapValues 함수를 실행할 때 파라미터 a, b가 Int 타입이면 두번째가 실행됨.
- 참고
지네릭 (Generics) - The Swift Language Guide (한국어)
Dictionary의 Key, Value와 같이 엘리먼트 간의 서로 상관관계가 있는 경우 의미가 있는 이름을 파라미터 이름으로 붙이고 그렇지 않은 경우는 T, U, V와 같은 단일 문자로 파라미터 이름을 짓습니다.
jusung.gitbook.io
Swift) 제네릭(Generic) 정복하기
안녕하세요 :) 소들입니다! 오늘의 두 번째 포스팅은 Generic에 대한 것입니다! 범용 타입이라구 하죠!! 어렵지 않은 문법이라 호딱 끝내 봅시다 :)) 모든 포스팅은 편의 말투로 합니다~!! 1. Generic이
babbab2.tistory.com
'iOS > Swift' 카테고리의 다른 글
Metatype(.self, .Type, .Protocol) (1) | 2023.11.08 |
---|---|
Swift Xcode 프로젝트명 바꾸기 (0) | 2023.08.01 |
Instance Method / prefix(_:), suffix(_:) (0) | 2023.06.06 |
Initializer / init(repeating:count:) (0) | 2023.06.06 |
Function / print(_:separator:terminator:) (0) | 2023.06.06 |