Swift 제네릭 프로그래밍 입문: 유연하고 재사용 가능한 코드 작성법
Swift 제네릭 프로그래밍 입문: 유연하고 재사용 가능한 코드 작성법
Swift는 강력하고 유연한 언어로, 다양한 프로그래밍 패러다임을 지원합니다. 특히 Swift의 제네릭(Generic)은 타입에 구애받지 않는 유연하고 재사용 가능한 코드를 작성할 수 있게 해줍니다. 이 글에서는 Swift 제네릭에 대해 설명하고 실제 코드 예제를 통해 제네릭을 어떻게 활용할 수 있는지 알아보겠습니다.
제네릭이란 무엇인가?
제네릭은 하나의 함수나 타입이 여러 다른 타입을 지원할 수 있게 만드는 기능입니다. 예를 들어, 배열(Array)은 특정 타입의 요소들을 담을 수 있지만, 이 타입이 무엇인지는 배열을 정의할 때 결정됩니다. 제네릭을 사용하면 배열과 같은 타입을 정의할 때 타입에 구애받지 않으며, 어떤 타입이든 지원할 수 있는 코드를 작성할 수 있습니다.
다음은 제네릭을 사용하지 않고 Int 배열의 모든 요소들의 합을 구하는 함수입니다:
swiftfunc sum(of numbers: [Int]) -> Int { var total = 0 for number in numbers { total += number } return total }
위 코드는 Int 타입에 대해서만 동작합니다. 만약 Double 타입에 대해서도 동작하는 함수를 작성하려면 어떻게 해야 할까요?
제네릭 함수 작성하기
제네릭을 사용하면 동일한 작업을 여러 타입에 대해 수행할 수 있는 함수를 작성할 수 있습니다. 제네릭 함수는 타입 매개변수를 사용하여 정의됩니다. 다음은 제네릭을 사용하여 여러 타입에 대해 동작하는 sum
함수를 정의하는 방법입니다:
swiftfunc sum<T: Numeric>(of numbers: [T]) -> T { var total: T = 0 for number in numbers { total += number } return total }
위 코드에서 T
는 타입 매개변수로, 함수가 호출될 때 결정됩니다. T
는 제네릭 매개변수의 일종이며, T: Numeric
부분은 T
가 Numeric
프로토콜을 준수해야 한다는 것을 의미합니다. 따라서, sum
함수는 Int 뿐만 아니라 Double, Float 등의 Numeric
프로토콜을 준수하는 타입에 대해서도 동작할 수 있습니다.
제네릭 타입 작성하기
함수뿐만 아니라 클래스, 구조체, 열거형에서도 제네릭을 사용할 수 있습니다. 다음은 제네릭을 사용하여 스택(Stack) 자료 구조를 작성하는 예제입니다:
swiftstruct 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 } }
여기서 Stack
은 제네릭 구조체로, Element
라는 타입 매개변수를 가집니다. 이 구조체의 메서드는 Element
타입의 요소들을 처리하는 메서드입니다. 따라서, Stack
은 Int, String 등 다양한 타입의 요소들을 지원할 수 있습니다.
제네릭 타입 사용 예제
제네릭 타입인 Stack
을 사용하는 예를 보겠습니다:
swiftvar intStack = Stack<Int>() intStack.push(1) intStack.push(2) print(intStack.pop() ?? 0) // 2 var stringStack = Stack<String>() stringStack.push(