정의
- 제네릭 코드는 유연하게 코드를 작성할 수 있습니다.
- 재사용함수와 자료형을 어떤 자료형이든 사용하여 작업할 수 있도록 요구사항을 정의합니다.
- 코드의 중복을 방지할 수 있습니다.
- 의도를 명확하게 표현하고 추상적인 방법으로 코드를 작성할 수 있습니다.
형식
- 코드의 중복과 코드를 유연하게 작성하기 위해 <T>로 자료형을 결정합니다.
- T는 함수에 넘겨진 타입의 값으로부터 추론하여 타입을 사용됩니다.
func 함수이름 <T> (매개변수명: inout T, 매개변수명: inout T){
// 코드작성
}
예제 1
제네릭을 사용하지 않는 함수
- 다음은 제네릭을 사용하지 않은 함수의 예제입니다.
- 3개의 함수 모두 동일한 기능을 갖고있지만 매개변수형만 다릅니다.
- in-out 인자를 통해 두 값( a와b )을 바꾸도록 구현하였습니다.
func swapInt(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapInt(&x, &y)
print(x, y)
func swapDouble(_ a: inout Double, _ b: inout Double) {
let temp = a
a = b
b = temp
}
var xd = 3.4
var yd = 9.8
swapDouble(&xd, &yd)
print(xd, yd)
func swapString(_ a: inout String, _ b: inout String) {
let temp = a
a = b
b = temp
}
var xs = "Hi"
var ys = "Hello"
swapString(&xs, &ys)
print(xs, ys)
실행결과
20 10
9.8 3.4
Hello Hi
제네릭을 사용한 함수
- 제네릭을 사용하면, 3개의 함수를 하나의 함수만으로 작성할 수 있습니다.
- 다음은 각각 swapInt, swapDouble, swapString 함수입니다.
func swapInt(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
func swapDouble(_ a: inout Double, _ b: inout Double) {
let temp = a
a = b
b = temp
}
func swapString(_ a: inout String, _ b: inout String) {
let temp = a
a = b
b = temp
}
- 위의 함수를 제네릭 함수로 변경한 모습입니다.
- 제네릭 함수는 자리 표시 타입 이름(T)을 실제 타입 이름(Int, Double, String,,) 대신 사용합니다.
- 실제 타입 사용은 swapAny 함수가 매번 호출 될 때마다 T가 결정합니다.
func swapAny<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
- 제네릭 함수를 통해 작성한 코드입니다.
- 3개의 다른 함수를 하나의 제네릭 함수로 작성해 코드의 중복이 없어지고 코드길이가 많이 줄었습니다.
func swapAny<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapAny(&x, &y)
print(x, y)
var xd = 3.4
var yd = 9.8
swapAny(&xd, &yd)
print(xd, yd)
var xs = "Hi"
var ys = "Hello"
swapAny(&xs, &ys)
print(xs, ys)
실행결과
- 3개의 함수를 사용했을 때와 동일한 결과가 출력됩니다.
20 10
9.8 3.4
Hello Hi
예제 2
Int형 스택 구조체
- push와 pop 기능을 갖고있는 스택 구조체를 만들겠습니다.
- 구조체는 value 타입이라 메서드 안에서 프로퍼티 값을 변경할 수 없습니다.
- 하지만 mutating 키워드를 사용하면 구조체 메서드 내에서 프로퍼티 값을 변경할 수 있습니다.
struct IntStack {
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
- push와 pop기능을 활용해 결과를 출력해보겠습니다.
struct IntStack {
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
var stackOfInt = IntStack()
print(stackOfInt.items)
stackOfInt.push(1)
print(stackOfInt.items)
stackOfInt.push(2)
print(stackOfInt.items)
stackOfInt.push(3)
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
실행결과
// []
// [1]
// [1, 2]
// [1, 2, 3]
// 3
// [1, 2]
// 2
// [1]
// 1
// []
generic 구조체를 사용한 스택 구조체
- 위와 동일한 기능, 목적을 가진 구조체입니다.
- Int형 구조체를 제네릭 구조체로 바꾼 코드입니다.
struct Stack<T> {
var items = [T]()
mutating func push(_ item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
- 제네릭을 사용한 구조체에서는 T형의 타입을 지정해줘야합니다.
- 이는 결정되지 않은 타입(자료형)을 <>안의 타입(자료형)으로 실행하겠다는 의미이기때문에 필수적인 요소입니다.
- 코드를 실행해보면 Int형 스택 구조체와 동일한 결과가 출력되는 것을 확인 할 수 있습니다.
struct Stack<T> {
var items = [T]()
mutating func push(_ item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var stackOfInt = Stack<Int>()
print(stackOfInt.items)
stackOfInt.push(1)
print(stackOfInt.items)
stackOfInt.push(2)
print(stackOfInt.items)
stackOfInt.push(3)
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
print((stackOfInt.pop()))
print(stackOfInt.items)
실행결과
// []
// [1]
// [1, 2]
// [1, 2, 3]
// 3
// [1, 2]
// 2
// [1]
// 1
// []
- 또한 다양한 타입(자료형)에 대해 같은 알고리즘으로 적용할 수 있습니다.
struct Stack<T> {
var items = [T]()
mutating func push(_ item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var stackOfInt = Stack<Int>()
print(stackOfInt.items)
stackOfInt.push(1)
print(stackOfInt.items)
stackOfInt.push(2)
print(stackOfInt.items)
stackOfInt.push(3)
print(stackOfInt.items)
var stackOfString = Stack<String>()
print(stackOfString.items)
stackOfString.push("가")
print(stackOfString.items)
stackOfString.push("나")
print(stackOfString.items)
stackOfString.push("다")
print(stackOfString.items)
실행결과
// []
// [1]
// [1, 2]
// [1, 2, 3]
// []
// ["가"]
// ["가", "나"]
// ["가", "나", "다"]
내용 출처
https://www.youtube.com/watch?v=Fun1Y4Bg3m4&list=PLJqaIeuL7nuEEROQDRcy4XxC9gU6SYYXb&index=43
https://docs.swift.org/swift-book/LanguageGuide/Generics.html
'iOS > Swift 문법 심화 학습' 카테고리의 다른 글
inout (0) | 2022.02.09 |
---|---|
mutating (0) | 2022.02.09 |
고차함수 [ map, filter, reduce ] (0) | 2022.02.07 |
오류 처리 [ error handling ] (0) | 2022.02.04 |
열거형 [ enum ] (0) | 2022.02.03 |
댓글