Swift에서 프로토콜을 확장할 때 where
절을 사용하여 특정 조건을 제약하는 방법은 매우 유용하다. 이를 통해 프로토콜 확장이 특정 타입, 제네릭 제약, 또는 프로토콜 준수 여부에 따라 적용되도록 제한할 수 있다. 아래는 다양한 예시와 활용법이다.
where
절을 사용해 특정 타입에 대해서만 확장을 제한할 수 있다.
protocol Greetable {
func greet()
}
extension Greetable where Self: String {
func greet() {
print("Hello, \(self)!")
}
}
extension String: Greetable {}
"Swift".greet() // 출력: Hello, Swift!
제네릭을 사용하는 프로토콜의 확장을 특정 타입이나 프로토콜에 한정할 수 있다.
protocol Summable {
func sum() -> Int
}
extension Array: Summable where Element == Int {
func sum() -> Int {
return self.reduce(0, +)
}
}
let numbers = [1, 2, 3, 4]
print(numbers.sum()) // 출력: 10
타입이 특정 프로토콜을 준수할 때만 확장을 적용할 수 있다.
protocol Describable {
var description: String { get }
}
extension Array where Element: Describable {
func describeAll() {
for element in self {
print(element.description)
}
}
}
struct Person: Describable {
var name: String
var description: String { return "Person: \(name)" }
}
let people = [Person(name: "Alice"), Person(name: "Bob")]
people.describeAll()
// 출력:
// Person: Alice
// Person: Bob
Equatable
제약을 추가한 활용타입이 Equatable
을 준수하는 경우에만 특정 기능을 제공할 수 있다.
extension Array where Element: Equatable {
func duplicates() -> [Element] {
var seen: Set<Element> = []
var duplicates: [Element] = []
for value in self {
if seen.contains(value) {
duplicates.append(value)
} else {
seen.insert(value)
}
}
return duplicates
}
}
let items = [1, 2, 3, 1, 2, 4]
print(items.duplicates()) // 출력: [1, 2]
프로토콜의 연관 타입(associated type)을 기반으로 확장을 제약할 수도 있다.
protocol Container {
associatedtype Item
var items: [Item] { get }
}
extension Container where Item == String {
func joinedItems() -> String {
return items.joined(separator: ", ")
}
}
struct StringContainer: Container {
var items: [String]
}
let container = StringContainer(items: ["Apple", "Banana", "Cherry"])
print(container.joinedItems()) // 출력: Apple, Banana, Cherry
where
절에서 여러 조건을 조합하여 사용할 수도 있다.
protocol Sortable {}
extension Array: Sortable where Element: Comparable {}
extension Sortable where Self: Array, Element: Comparable {
func sortedArray() -> [Element] {
return self.sorted()
}
}
let values = [3, 1, 4, 1, 5]
if let sortable = values as? [Int] & Sortable {
print(sortable.sortedArray()) // 출력: [1, 1, 3, 4, 5]
}