티스토리 뷰

//제네릭을 사용하기 위해 프로토콜 정의
protocol Personalize {
    var name: String { get }
    var age: Int { get }
}

struct Person: Personalize {
    var name: String
    var age: Int
}

let star: Person = Person(name: "Star", age: 99)

//제네릭을 사용하여 패턴 연산자를 정의
func ~= <T: Personalize>(pattern: String, value: T) -> Bool {
    return pattern == value.name
}

func ~= <T: Personalize>(pattern: T, value: T) -> Bool {
    return pattern.name == value.name && pattern.age == value.age
}

//기존 패턴 연산자가 없더라도 제네릭 패턴 연산자로 똑같이 사용할 수 있다.
switch star {
case Person(name: "Star", age: 99): print("Same Person!")
case "Star": print("Hello Star!!")
default: print("I don't know who you are")
} //Same Person!!

//이번엔 제네릭을 사용하여 패턴 연산자를 정의
//패턴 자체가 함수임!!
func ~= <T:Personalize>(pattern: (T) -> Bool, value: T) -> Bool {
    return pattern(value)
}

//패턴에 사용할 제네릭 함수
func young<T: Personalize>(value: T) -> Bool {
    return value.age < 50
}

switch star {
//패턴결합을 하면 young(star)와 같은 효과를 본다.
case young: print("\(star.name) is young")
default: print("\(star.name) is old")
} //Star is old

//패턴에 사용할 제네릭 함수
func isNamed<T: Personalize>(_ pattern: String) -> ((T) -> Bool) {
    return { (value: T) -> Bool in value.name == pattern }
    //패턴과 값을 비교할 클로저를 반환한다.
}

switch star {
//패턴결합을 하면 isNamed("Jung")(star)와 같은 효과를 본다.
case isNamed("Jung"): print("He is Jung")
default: print("Another person")
} //Another person

//연산자가 함수라는 점을 생각해보면 이런 방식으로도 구현할 수 있다.
prefix operator ==?

prefix func ==? <T:Personalize>(pattern: String) -> ((T) -> Bool) {
    return isNamed(pattern)
}

switch star {
//패턴결합을 하면 isNamed("Jung")(star)와 같은 효과를 본다.
case ==?"Jung": print("He is Jung")
default: print("Another person")
} //Another person

 

Same Person!
Star is old
Another person
Another person

 

: 패턴에 함수를 사용해서 함수의 결과를 통해 Bool 값을 얻어냈다. 단순히 패턴에 함수를 사용하는 것을 넘어서 제네릭을 사용하여 프로토콜을 준수하는 타입 모두가 공통으로 매칭이 될 수 있다는 점은 굉장히 매력적!! 또한, 사용자 정의 연산자를 적극 활용할 수 있으므로 재미있는 활용법도 무궁무진하게 구상해볼 수 있다 ~~

 

이런 방법은 사용해보지 않았는데 기억 한 켠에 저장해두면 언젠가 유용하게 사용해볼 수 있을 듯..!!!!

 

 

출처 : 스위프트 프로그래밍 3판

댓글