새소식

iOS/Swift

[Swift] 제네릭

  • -
참조 :  Swift 스위프트 프로그래밍 3판 Swift 5, 저자 야곰 (한빛미디어) , The Swift Programming Language Swift 5.6 Edition
 (iBooks)(https://books.apple.com/kr/book/the-swift-programming-language-swift-5-6/id881256329)

 

 

제네릭(Generic)


- 스위프트 표준 라이브러리 또한 수많은 제네릭 코드로 구성

- 스위프트의 강력한 기능 중 하나

- 제네릭으로 구현한 기능과 타입 → 재사용하기 쉬움, 깔끔하고 추상적인 표현 가능

- Array, Dictionary, Set등의 타입은 모두 제네릭 컬렉션

 

- 제네릭을 사용할 때는 제네릭이 필요한 타입 또는 메서드의 이름 뒤의 (<>)에 제네릭을 위한
타입 매개변수를 써 제네릭을 사용할 것을 표시

- Array 타입 매개변수 : Element, map 메서드의 타입 매개변수 : T

→ Array는 제네릭 타입, map 메서드는 제네릭 함수

 

 

 

 

제네릭 함수


- 같은 타입인 두 변수의 값을 교환한다는 목적을 타입에 상관없이 할 수 있도록 단 하나의 함수로 구현 가능

- 제네릭을 사용한 swapTwoValue(_:_:) 함수

func swapTwoValue<T>(_ a: inout T, _ b: inout T) {
    let temporaryA: T = a
    a = b
    b = temporaryA
}

var numberOne: Int = 5
var numberTwo: Int = 10

var stringOne: String = "A"
var stringTwo: String = "B"

var anyOne: Any = 1
var anyTwo: Any = "Two"

swapTwoValue(&numberOne, &numberTwo)
print("\(numberOne), \(numberTwo)") // 10, 5

swapTwoValue(&stringOne, &stringTwo)
print("\(stringOne), \(stringTwo)") // B, A

swapTwoValue(&anyOne, &anyTwo)
print("\(anyOne), \(anyTwo)") // Two, 1

※ 같은 타입끼리만 교환 가능

 

- 실제 타입 이름(Int, String 등)을 써주는 대신에 플레이스홀더(Placeholder, 위 함수에서는 T)를 사용

- 플레이스홀드(T)는 타입의 종류를 알려주지 않지만 말 그대로 어떤 타입이라는 것은 알려줌

- 플레이스홀더 타입이 T인 매개변수가 있음 → 두 매개변수는 같은 타입임

- Int 타입의 변수가 전달인자로 전달됨 → T는 Int

- String 타입의 변수가 전달인자로 전달됨 → T는 String

 

- 플레이스홀더를 지정하는 방법 : <> 안에 플레이스홀더 이름들을 나열, 여러 타입의 매개변수를 지정 → <T, U, V>

- 타입 매개변수를 지정 → 함수의 매개변수, 반환 타입, 내부 변수의 타입 지정을 위해 사용 가능

 

 

 

제네릭 타입


- Stack : 배열과 유사하게 순서가 있는 값들의 모임, 제네릭 컬랙션 타입 중 하나

- Stack은 컬렉션의 끝 부분에서만 요소를 추가하고 삭제할 수 있음

- 추가를 Push, 삭제를 Pop이라고 칭함

 

 

struct Stack<Element>{
    var items = [Element]()
    mutating func push(_ item: Element){
        items.append(item)
    }
    mutating func pop() -> Element{
        return items.removeLast()
    }
}

var doubleStack: Stack<Double> = Stack<Double>()

doubleStack.push(1.0)
print(doubleStack.items) // [1.0]

doubleStack.push(2.0)
print(doubleStack.items) // [1.0, 2.0]

doubleStack.pop()
print(doubleStack.items) // [1.0]

 

items 배열의 타입을 Any로 지정 (Element)

 

타입 제약(Type Constraints)


- 타입 매개변수가 가져야 할 제약사항을 지정하는 방법

- 클래스 타입 또는 프로토콜로만 줄 수 있음 → 열거형, 구조체 등의 타입은 사용 불가

- 여러 제약 조건을 추가하고 싶다면 where절을 사용

- 제네릭의 타입제약 추가

func swapTwoValues<T: BinaryInteger>(_ a: inout T, _ b: inout T) where T:
    FloatingPoint{
        // 함수 구현
    }

 

- 타입 제약에 자주 사용하는 프로토콜 : Hashable, Equatable, Comparable, Indexable, IteratorProtocol, Error, Collection 등 

 

 

 

프로토콜의 연관타입(Associated Type)


- 어떤 타입이 들어올지 모를 때, 타입 매개변수를 통해 '종류는 알 수 없지만, 어떤 타입이 여기에 쓰일 것이다'라고 표현

→ 연관 타입은 타입 매개변수의 그 역활을 프로토콜에서 수행할 수 있도록 만들어진 기능

- Container 프로토콜

protocol Container{
    associatedtype Itemtype
    var count: Int {get}
    mutating func append(_ item: Itemtype)
    // mutating : 해당 메서드가 인스턴스 내부의 값을 변경한다고 명시할 때 사용
    subscript(i: Int) -> Itemtype {get}
}

 

- Container 프로토콜을 준수하는 타입

  • 컨테이너의 새로운 아이템을 append(_:) 메서드를 통해 추가
  • 아이템 개수를 확인하기 위해 count 프로퍼티 구현
  • Int 타입의 인덱스 값으로 특정 인덱스에 해당하는 아이템을 가져올 수 있는 서브스크립트 구현

 

 

- Container 프로토콜을 준수하는 MyContainer 클래스 정의

class MyContainer: Container {
    var items: Array<Int> = Array<Int>()
    
    var count: Int{
        return items.count
    }
    func append(_ item: Itemtype) {
        items.append(item)
    }
    
    subscript(i: Int) -> Int {
        return items[i]
    }
}

 

 

- IntStack 구조체의 Container 프로토콜 준수

struct IntStack: Container{
    var items = [Int]()
    mutating func push(_ item: Int){
        items.append(item)
    }
    mutating func pop(_ item: Int) -> Int{
        return items.removeLast()
    }
    
    mutating func append(_ item: Itemtype) {
        self.push(item)
    }
    var count: Int{
        return items.count
    }
    subscript(i: Int) -> Int {
        return items[i]
    }
    
}
728x90

'iOS > Swift' 카테고리의 다른 글

[Swift] NotificationCenter  (0) 2023.04.16
[Swift] Localizable  (0) 2023.03.18
[Swift] for문  (0) 2023.02.07
[Swift] UnsafePointer, UnsafeMutablePointer  (0) 2023.01.08
[Swift] 소수점 없애기  (0) 2023.01.01
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.