본문 바로가기
Swift

제네릭(Generics)

by JDeoks 2023. 10. 4.

https://developer.apple.com/documentation/swift/array/map(_:)-87c4d 

 

map(_:) | Apple Developer Documentation

Returns an array containing the results of mapping the given closure over the sequence’s elements.

developer.apple.com

map(_:) 함수를 공부하던 중 제대로 정립되지 않은 개념이 있어서 정리한다.

map(_:) 함수는 클로저를 사용하여 배열의 각 요소를 처리하고, 그 결과를 새로운 배열로 반환하는 함수이며, 다음과 같이 생겼다.

func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]

함수 이름 뒤에 <T>는 타입 파라미터라고 하는데, 해당 함수가 제네릭 함수임을 나타낸다.

여기서 제네릭이란 다양한 데이터 타입에서 동작하는 코드를 작성하기 위한 방법으로, 독립적인 코드를 작성하고, 코드의 재사용성과 유지 보수성을 향상시키는 데 도움을 준다.

 

만약 제네릭을 사용하지 않는다면 아래와 같이 각각의 데이터 타입에 대해 중복된 코드를 작성해야 한다.

func sortIntegers(array: [Int]) -> [Int] {
    // 정수 배열 정렬
}
func sortStrings(array: [String]) -> [String] {
    // 문자열 배열 정렬
}

이는 다음과 같은 제네릭 함수로 대체할 수 있다.

func sort<T: Comparable>(array: [T]) -> [T] {
    // T 배열 정렬
}

굉장히 깔끔해졌는데, 정리하면

Comparable이라는 프로토콜을 만족하는 어떤 자료형인 T로 이루어진 배열을 정렬해서 반환하는 함수가 되는 것이다.

 

클래스, 구조체, 열거형과 같은 사용자 정의 타입을 작성할때는 제네릭 타입을 사용할 수 있다.

다음은 제네릭을 이용한 스택 구조체의 예시이다.

struct Stack<Element> {
    private var elements: [Element] = []
    mutating func push(_ element: Element) {
        elements.append(element)
    }
    mutating func pop() -> Element? {
        return elements.popLast()
    }
    func peek() -> Element? {
        return elements.last
    }
    var isEmpty: Bool {
        return elements.isEmpty
    }
    var count: Int {
        return elements.count
    }
}

여기서는 <Element>가 바로 타입 파라미터이다. 임의로 바꿔도 되지만 보편적으로 제네릭함수에서는 <T>, 제네릭 타입에서는 <Element>를 사용한다.