일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- designPattern
- enumerations
- protocol
- dart
- basic
- Equatable
- tip
- GIT
- Swift
- swiftlint
- ToDoRim
- Extentsion
- pubspec
- keyWindow
- IOS
- COMMIT
- pubspec.yaml
- xcode
- flutter
- listview
- algorithm
- OSLog
- reetcode
- Leetcode
- github
- UIAccessibility
- toyproject
- SwiftGen
- Widget
- it
- Today
- Total
수니의 개발새발
[iOS/Swift] Generic 본문
📌 이번 글은
Generic 개념과 사용법입니다.
The Swift Programming Language Guide - Generic
Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code.
For example, Swift’s Array and Dictionary types are both generic collections.
Generics는 Swift의 가장 강력한 기능 중 하나이며 Swift 표준 라이브러리의 대부분은 Generic 코드로 빌드됩니다.
예를 들어, Swift의 Array와 Dictionary 유형은 모두 Generic Collection입니다.
Generic 개념
Generic은 타입에 유연하게 대처합니다. - 타입에 의존하지 않고 범용적인 코드를 작성할 때 사용합니다.
Generic은 코드를 유연하게 작성할 수 있습니다. - Generic으로 구현한 기능과 타입은 재사용에 용이하고, 코드의 중복을 피할 수 있습니다.
Generic의 예로는 Array, Dictionary, Set 등이 있는데, 이들의 요소로 Int형과 String형 등을 갖는 배열을 만들 수 있는 이유가 Generic 덕분입니다.
Generic 함수
Generic을 사용하지 않는 함수 - 코드 중복
Int형 값을 스왑
// Generic을 사용하지 않은 일반 함수
/// Int형 값 스왑
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
만약 Int형이 아닌 다른 형의 값을 스왑 하고 싶을 때
/// Double형 값 스왑
func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {
let temp = a
a = b
b = temp
}
/// String형 값 스왑
func swapTwoStrings(_ a: inout String, _ b: inout String) {
let temp = a
a = b
b = temp
}
위와 같이 만들어 줘야 합니다... 코드의 중복을 피할 수 없게 되죠.
이때 Generic을 사용하여 코드의 중복을 피하고, 재사용성을 높입니다.
Generic 함수 선언
타입에 의존하지 않고 두 값을 스왑 하는 Generic 함수를 생성합니다.
// Generic 함수
/// 두 개의 값을 스왑
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
T (Type Parameter:Placeholder)
- 타입의 종류를 지정하지 않지만, 어떠한 타입이 들어올 것을 의미합니다.
- T는 함수가 호출될 때마다 타입이 결정됩니다.
Generic함수 사용
Generic함수는 원하는 타입을 넣어 사용할 수 있습니다.
이때, 스왑하는 두 값은 같은 타입이어야 합니다.
Swift는 타입에 안전한 언어이기 때문에 다른 타입의 값을 바꾸는 것을 허용하지 않습니다.
시도할 경우, 컴파일 오류가 발생할 것입니다.
var someInt = 3
var aotherInt = 323
// 함수 호출 시 T는 Int 타입으로 결정됨
swapTwoValues(&someInt, &aotherInt)
var someString = "Suni"
var aotherString = "Mora"
// 함수 호출 시 T는 String 타입으로 결정됨
swapTwoValues(&someInt, &aotherInt)
Generic 타입
struct, class, enum 에도 Generic을 사용할 수 있습니다.
Generic을 사용하지 않은 구조체 (struct)
Int형 값만 Stack 기능을 수행하는 구조체(sturct)입니다. 역시 타입에 의존합니다.
// Generic을 사용하지 않은 일반 구조체
/// Int형 값만 Stack 기능을 수행
struct StackInt {
var items: [Int] = []
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}
Generic 구조체(sturct) 선언
함수와 같이 T(Type Parameter:Placeholder)를 사용하여
타입에 의존하지 않고 Stack기능을 수행하는 Generic 구조체(struct)를 생성합니다.
// Generic struct
/// Stack 기능 수행
struct Stack<T> {
var items: [T] = []
mutating func push(_ item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
Generic 구조체(sturct) 생성
<>에 사용할 타입을 명시하여 생성합니다.
// Generic 구조체 사용
let stack1: Stack<Int> = .init()
let stack2 = Stack<Int>.init()
타입 제약
타입에 의존하지 않는 Generic에도 타입에 제약을 두고 싶을 때, 사용하는 방법입니다.
타입 제약은 프로토콜(Protocol)과 클래스(class)에서만 가능합니다.
즉, Generic 함수와 타입을 사용할 때 특정 클래스의 하위 클래스나, 특정 프로토콜을 준수하는 타입만 받을 수 있게 제약을 둘 수 있다.
타입 제약 사용 방법
T: BinaryInteger 와 같이 타입에 제약 추가
여러 제약을 추가하고 싶을 때에는 whare절 사용
// T가 BinaryInteger Protocol을 준수하는 Generic 함수
func swapTwoValues<T: BinaryInteger>(_ a: inout T, _ b: inout T) {
// code ...
}
// T가 BinaryInteger, FloatingPoint Protocol을 준수하는 Generic 함수
func swapTwoValuesPlusConstraint<T: BinaryInteger>(_ a: inout T, _ b: inout T) where T: FloatingPoint {
// code ...
}
예를 들어, 두 값의 동일 여부를 반환하는 Generic 함수 생성 >> ERROR
Binary operator '==' cannot be applied to two 'T' operands
이진 연산자 '=='는 두 개의 'T' 피연산자에 적용할 수 없습니다.
Swift에서는 '=='/'!=' 연산자는 Equatable 프로토콜을 준수해야 사용할 수 있습니다.
T에 Equatable을 준수하지 않은 타입이 올 수도 있으니, '=='를 사용하지 못한다는 오류가 발생합니다.
Equatable 참고 포스팅
T가 Equatable을 준수하도록 타입 제약 추가
이제 isEqualValue 함수는 Equatable을 준수하는 타입의 파라미터만 받을 수 있습니다!
🙋🏻♀️ 참고
Swift(4) - Generic(제네릭)이란 무엇일까?
'iOS - Swift' 카테고리의 다른 글
[iOS/Swift] SwiftGen 적용하기 (pod 'SwiftGen') (0) | 2022.02.04 |
---|---|
[iOS/Swift] typealias (0) | 2022.02.02 |
[iOS/Swift] Identifiable (0) | 2022.01.26 |
[iOS/Swift] Equatable (0) | 2022.01.25 |
[iOS/Swift/Basic] 튜플 Tuple (0) | 2022.01.22 |