반환 타입에 불명확 타입(Opaque Types)을 사용하면 반환할 타입의 정확한 타입을 알려주지 않은채로 반환하겠다는 것을 의미한다.
프로퍼티나 서브스크립트의 선언 혹은 함수의 반환 타입 위치에 프로토콜을 쓰면서 앞에 some을 붙이면, '이 프로토콜을 준수하는 어떤 타입 중에 하나일 것은 분명하다'는 뜻이다. 언뜻 보면 제네릭과 비슷해 보이지만 많이 다르다. 제네릭은 정의해 줄 때 정확히 어떤 타입이 들어올지 모르는 상태로 플레이스 홀더를 만들어 준다. 불명확 타입은 반대로 외부에서는 어떤 타입이 나에게 반환될지 모른다. 다시 말해서 제네릭은 외부에서 타입을 지정해 주는 것이고, 불명확 타입은 내부에서 타입을 정해서 내보내게 되는데, 밖에서는 정확히 어떤 타입인지는 몰라도 쓸 수 있는 것이다. 그래서 '역제네릭 타입'이라고 표현하기도 한다.
다시 한 번 생각해보면 '어떤 프로토콜을 따르는 타입을 반환할 것인데 그 타입을 명확히는 알려주지 않겠다' 정도로 생각해 볼 수 있다. 그러면 그냥 프로토콜을 반환 타입으로 정의해 주면 되는 것 아닌가?라고 생각할 수도 있지만 프로토콜 정의부에 associatedType을 사용했거나, Self 타입을 사용하는 프로토콜이라면 타입 자체가 제네릭하게 되므로 반환 타입으로 사용할 수 없다. 예를 들어 살펴보자.
여러 종류의 피규어를 임의로 배출하는 뽑기 기계가 있다고 가정해 보자. 뽑기는 포장을 열어보기 전까지는 어떤 상품이 들어있는지 알 수 없다. 그래서 포장된 상품을 [코드 30-1]에서 프로토콜로 정의했다.
/*
코드 30-1. 뽑기 상품 프로토콜 정의
*/
// 포장된 상품을 표현
protocol WrappedPrize {
associatedtype Prize
var wrapColor: String! { get } // 포장 색상
var prize: Prize! { get } // 실제 상품
}
그리고 실제로 포장된 상품을 [코드 30-2]처럼 구조체로 표현해 보자.
/*
코드 30-2. 포장된 상품 프로토콜 정의
*/
protocol Gundam {}
protocol Pokemon {}
struct WrappedGundam: WrappedPrize {
var wrapColor: String!
var prize: Gundam!
}
struct WrappedPokemon: WrappedPrize {
var wrapColor: String!
var prize: Pokemon!
}
이제 뽑기 기계를 만들어보자. 뽑기 기계는 임의의 포장된 상품을 내어주어야 한다. 먼저 [코드 30-3]처럼 시도해 보자.
/*
코드 30-3. 뽑기 기계 구조체 정의
*/
struct PrizeMachine {
func dispenseRandomPrize() -> WrappedPrize {
return WrappedGundam()
}
}
그러나 [코드 30-3]은 WrappedPrize는 제네릭 타입 제약이 있어야만 사용할 수 있는 타입이기 때문에 WrappedPrize 자체 만으로는 반환 타입이 될 수 없다고 오류를 뱉어낸다. WrappedPrize 프로토콜의 연관 타입인 Prize를 추론할 힌트를 얻지 못하기 때문이다. 그래서 아래 [코드 30-4]처럼 some을 앞에 붙여서 불명확 타입으로 개선해보았다.
/*
코드 30-4. 뽑기 기계 구조체 개선
*/
struct PrizeMachine {
func dispenseRandomPrize() -> some WrappedPrize {
return WrappedGundam()
}
}
let machine: PrizeMachine = PrizeMachine()
let wrappedPrize = machine.dispenseRandomPrize()
이제 기계가 잘 동작하는 것 같다.
이처럼 외부에서는 정확한 타입은 알 수 없지만, 해당 프로토콜을 준수하는 어떤 타입인가를 반환한다는 약속을 불명확 타입으로 표현할 수 있다. 불명확 타입은 함수 (메서드)의 반환 타입뿐만 아니라 프로퍼티나 서브스크립트의 타입에도 사용할 수 있다.
'iOS > SWIFT' 카테고리의 다른 글
[Swift] Chapter 29. 메모리 안전 (0) | 2021.10.24 |
---|---|
[Swift] Chapter 28. 오류처리 (0) | 2021.10.24 |
[Swift] Chapter 27. ARC (0) | 2021.10.23 |
[Swift] Chapter 26. where 절 (0) | 2021.10.23 |
[Swift] Chapter 25. 패턴 (0) | 2021.10.23 |
댓글