🔥 제네릭 Where 절을 사용한 확장
제네릭 where
절은 확장의 일부로도 사용할 수 있어요. 아래 예제는 이전 예제에서 다룬 제네릭 Stack
구조체를 확장하여 isTop(_:)
메서드를 추가하는 걸 보여주고 있습니다.
extension Stack where Element: Equatable { func isTop(_ item: Element) -> Bool { guard let topItem = items.last else { // 스택이 비어있으면 false를 반환해요. return false } // 주어진 item과 스택의 최상위 item을 비교하는 거예요. return topItem == item } }
swift
이 새로운 isTop(_:)
메서드는 먼저 스택이 비어있는지 확인하고, 그렇지 않으면 주어진 item과 스택의 최상위 item을 비교합니다. 만약 제네릭 where
절 없이 이를 시도한다면, 문제가 생길 거예요. isTop(_:)
메서드의 구현은 ==
연산자를 사용하지만, Stack
의 정의는 그 항목들이 동등 비교가 가능할 것을 요구하지 않거든요. 따라서 ==
연산자를 사용하면 컴파일 시간 오류가 발생하게 됩니다. 제네릭 where
절을 사용하면 확장에 새로운 요구사항을 추가할 수 있어서, 스택의 항목들이 동등 비교 가능할 때에만 isTop(_:)
메서드를 추가할 수 있게 돼요.
아래는 isTop(_:)
메서드가 실제로 어떻게 동작하는지 보여주는 예시입니다.
if stackOfStrings.isTop("tres") { print("Top element is tres.") } else { print("Top element is something else.") } // "Top element is tres."를 출력해요.
swift
만약 동등 비교가 불가능한 요소들로 이루어진 스택에서 isTop(_:)
메서드를 호출하려고 하면, 컴파일 시간 오류가 발생할 거예요.
struct NotEquatable { } var notEquatableStack = Stack<NotEquatable>() let notEquatableValue = NotEquatable() notEquatableStack.push(notEquatableValue) notEquatableStack.isTop(notEquatableValue) // 오류가 나겠죠?
swift
제네릭 where
절은 프로토콜 확장에서도 사용할 수 있답니다. 아래 예제는 이전 예제에서 다룬 Container
프로토콜을 확장하여 startsWith(_:)
메서드를 추가하는 걸 보여주고 있어요.
extension Container where Item: Equatable { func startsWith(_ item: Item) -> Bool { // 컨테이너에 적어도 하나의 항목이 있는지 확인하는 거예요. return count >= 1 && self[0] == item } }
swift
startsWith(_:)
메서드는 먼저 컨테이너에 적어도 하나의 항목이 있는지 확인하고, 그 후에 컨테이너의 첫 번째 항목이 주어진 항목과 일치하는지 확인합니다. 이 새로운 startsWith(_:)
메서드는 위에서 사용된 스택과 배열을 포함하여, Container
프로토콜을 따르는 모든 타입에서 사용될 수 있어요. 단, 컨테이너의 항목들이 동등 비교 가능해야 한다는 점, 잊지 마세요!
if [9, 9, 9].startsWith(42) { print("Starts with 42.") } else { print("Starts with something else.") } // "Starts with something else."를 출력하겠죠?
swift
위의 예제에서 제네릭 where
절은 Item
이 프로토콜을 따를 것을 요구하지만, Item
이 특정 타입일 것을 요구하는 제네릭 where
절을 작성할 수도 있어요. 예를 들면 이런 식으로요.
extension Container where Item == Double { func average() -> Double { var sum = 0.0 for index in 0..<count { sum += self[index] } // count를 Int에서 Double로 명시적으로 변환하여 부동 소수점 나눗셈을 할 수 있도록 하는 거예요. return sum / Double(count) } } print([1260.0, 1200.0, 98.6, 37.0].average()) // "648.9"를 출력하게 될 거예요.
swift
이 예제는 Item
타입이 Double
인 컨테이너에 average()
메서드를 추가하고 있습니다. 이 메서드는 컨테이너의 항목들을 순회하면서 합계를 구하고, 컨테이너의 개수로 나누어 평균을 계산하는 거죠.
확장의 일부로 작성하는 제네릭 where
절에서는 다른 곳에서 제네릭 where
절을 작성할 때처럼 여러 개의 요구사항을 포함시킬 수 있어요. 목록에서 각 요구사항은 쉼표로 구분하면 된답니다.
제네릭 where
절을 활용하면 제네릭 코드의 유연성과 표현력을 크게 높일 수 있습니다. 이를 통해 특정 타입이나 프로토콜을 따르는 타입들에 대해서만 추가적인 기능을 제공하는 확장을 작성할 수 있게 되는 거죠. 이런 방식으로 제네릭 코드의 재사용성을 향상시키면서도, 타입 안전성을 유지할 수 있게 됩니다.
다음은 제네릭 where
절의 활용 예시를 시각화한 다이어그램이에요.
이 다이어그램은 제네릭 타입이 제네릭 where
절을 가진 확장을 통해, 특정 타입이나 프로토콜을 따르는 타입들에 대해 추가 기능을 제공할 수 있다는 걸 보여주고 있죠. 이런 방식으로 제네릭 프로그래밍의 강력함과 유연성을 활용할 수 있답니다.
어떤가요? 제네릭 where
절의 매력을 느낄 수 있었나요? 이를 활용하면 더 강력하고 유연한 제네릭 코드를 작성할 수 있을 거예요. 한번 직접 사용해보는 건 어떨까요?