Opaque type의 특징은 caller는 해당 값이 구체적으로 어떤 것인지 알수 없다는 점입니다.
그래서 이름도 불확실하다는 의미에서 opaque인 거겠죠?
그렇다면 이런 opaque type이 왜 구체적인 타입을 숨기는 지, 숨김으로써 얻게 되는 이점은 무엇인지 알아보겠습니다.
아래 예시를 보면, Farm이라는 객체 안에 hungryAnimals라는 Collection타입의 변수가 있고 해당 변수를 looping하며 연산을 하는 feedAnimals()라는 메서드가 있습니다.
extension Farm {
var hungryAnimals: LazyFilterSequence<[any Animal]> {
animals.lazy.filter(\.isHungry)
}
func feedAnimals() {
for animal in hungryAnimals {
// ...
}
}
}
여기서 hungryAnimals의 타입은 LazyFilterSequence<[any Animal]> 입니다. 구체적으로 잘 나와있어서 좋을 수도 있으나, feedAnimals에서는 그저 Collection을 loop하기만 하면 되기때문에, 오히려 사용 시에 타입에 대한 혼란을 줄 수 있는 여지도 있습니다.
이럴 때, 불필요한 정보를 숨기고 핵심적인 정보만 주기 위해서 사용되는 것이 바로 Opaque type입니다.
Opaque type을 사용하면 LazyFilterSequence<[any Animal]>을 훨씬 간단하게 표현할 수 있습니다.
var hungryAnimals: some Collection {
animals.lazy.filter(\.isHungry)
}
결국 LazyFilterSequence<[any Animal]>도 Collection type이기 때문에, some Collection으로 표현이 가능합니다.
이렇게 바꾸어 놓으니 훨씬 보기에도 깔끔하고, Collection type이니까 iterate이 가능하겠구나 라는 정도의, 사실상 feedAnimals가 알아야 했던 유일한 정보도 전달할 수 있는 것입니다.
그런데 이렇게 수정하고 사용하려다 보니, 이제는 막상 너무 타입에 대한 정보가 없어서 Collection 안에 무슨 타입의 데이터가 있는 지도 알기 어려워졌습니다. 그래서 Animal만이 가지고 있는 고유의 프로퍼티나 메서드에 접근이 불가능해지게 되었습니다.
이러한 문제를 해결하기 위해서는 type을 어느 정도 제한해 주어야 합니다.
var hungryAnimals: some Collection<any Animal> { // Opaque type의 type 제한
animals.lazy.filter(\.isHungry)
}
이렇게 <>안에 제한할 타입을 명시해주면, 정확한 타입을 숨길 수 있을 뿐만 아니라, 사용되는 중요한 정보는 알려줄 수 있어서 Caller가 편리하게 사용할 수 있게 됩니다. Caller는 이제 hungryAnimals가 정확히 어떤 Collection인지는 모르지만 Collection 중 하나의 타입이며, Collection의 내 (Element라는) associatedtype이 any Animal이라는 것을 알 수 있는 것입니다.
참고자료
https://developer.apple.com/videos/play/wwdc2022/110353/
'Swfit' 카테고리의 다른 글
super.viewDidLoad를 호출하는 이유 (1) | 2024.03.21 |
---|---|
Struct에서 mutating function을 사용하는 이유 (0) | 2024.02.08 |
some에 대해 알아보기 (any와 비교) (2) | 2024.01.22 |
WidgetKit - Timeline Provider (1) | 2024.01.19 |
SupaBase Swift로 사용해보기 (0) | 2024.01.08 |