🔥 컨텍스트 Where 절
Swift에서는 제네릭 타입 제약 조건이 없는 선언의 일부로 제네릭 where
절을 작성할 수 있어요. 이는 이미 제네릭 타입의 컨텍스트에서 작업하고 있을 때 유용하게 사용된답니다.
예를 들어, 제네릭 타입의 서브스크립트나 제네릭 타입의 확장에 있는 메서드에 제네릭 where
절을 작성할 수 있지요. 아래 예제에서 Container
구조체는 제네릭이고, where
절은 이러한 새로운 메서드를 컨테이너에서 사용할 수 있도록 하기 위해 어떤 타입 제약 조건이 충족되어야 하는지를 지정하고 있어요.
extension Container { func average() -> Double where Item == Int { // 요소들의 합을 저장할 변수 var sum = 0.0 // 컨테이너의 모든 요소를 순회하면서 for index in 0..<count { // 각 요소를 Double로 변환하여 합에 더함 sum += Double(self[index]) } // 합을 요소 개수로 나누어 평균을 구함 return sum / Double(count) } func endsWith(_ item: Item) -> Bool where Item: Equatable { // 컨테이너의 마지막 요소가 주어진 item과 같은지 확인 return count >= 1 && self[count-1] == item } } let numbers = [1260, 1200, 98, 37] print(numbers.average()) // "648.75" 출력 print(numbers.endsWith(37)) // "true" 출력
swift
이 예제는 Item
타입이 Int
일 때 Container
에 average()
메서드를 추가하고, Item
타입이 Equatable
을 준수할 때 endsWith(_:)
메서드를 추가한답니다. 두 함수 모두 원래 Container
의 선언에서 제네릭 Item
타입 매개변수에 타입 제약 조건을 추가하는 제네릭 where
절을 포함하고 있죠.
만약 컨텍스트 where
절을 사용하지 않고 이 코드를 작성하려면, 각 제네릭 where
절에 대해 하나씩 두 개의 확장을 작성해야 해요. 위의 예제와 아래의 예제는 동일하게 동작합니다.
extension Container where Item == Int { func average() -> Double { var sum = 0.0 for index in 0..<count { sum += Double(self[index]) } return sum / Double(count) } } extension Container where Item: Equatable { func endsWith(_ item: Item) -> Bool { return count >= 1 && self[count-1] == item } }
swift
컨텍스트 where
절을 사용한 버전의 예제에서는 average()
와 endsWith(_:)
의 구현이 모두 동일한 확장에 있어요. 각 메서드의 제네릭 where
절은 해당 메서드를 사용할 수 있도록 만들기 위해 충족되어야 하는 요구 사항을 명시하고 있기 때문이죠.
이러한 요구 사항을 확장의 제네릭 where
절로 이동하면 메서드를 동일한 상황에서 사용할 수 있지만, 요구 사항마다 하나의 확장이 필요하게 된답니다.
이렇게 컨텍스트 where
절을 사용하면 관련된 제약 조건을 하나의 확장에 모아서 표현할 수 있어 코드의 가독성과 응집성을 높일 수 있어요. 반면 제약 조건마다 별도의 확장을 작성하는 것은 코드를 분산시켜 오히려 복잡성을 증가시킬 수 있겠죠.
따라서 컨텍스트에 맞게 적절한 방식을 선택하여 제네릭 where
절을 활용한다면, 더욱 간결하고 표현력 있는 코드를 작성할 수 있을 거예요.