🌟 불투명(opaque) 반환 타입
을 가진 함수나 메소드는 반환 값의 타입 정보
를 숨김
🌟 함수의 반환 타입으로 고정(concrete)타입
을 제공하는 대신 반환 값을 자신이 지원하는 프로토콜로 설명
🌟 타입 정보를 감추는 것은 반환 값의 실제 타입을 개인 전용(private)
으로 남길 수 있기 때문에 모듈과 그 모듈을 호출하는 코드의 경계선 상에서 유용
🌟 프로토콜 타입인 값을 반환하는 것과는 달리, 불투명 타입
은 타입 정체성(type identity)
을 보존
🌟 컴파일러는 타입 정보
에 접근할 수 있지만, 모듈 사용자는 접근불가
protocol Shape {
func draw() -> String
}
struct Triangle: Shape {
var size: Int
func draw() -> String {
var result = [String]()
for length in 1...size {
result.append(String(repeating: "*", count: length))
}
return result.joined(separator: "\n")
}
}
let smallTriangle = Triangle(size: 3)
print(smallTriangle.draw())
💻 출력 :
*
**
***
struct FlippedShape<T: Shape>: Shape {
var shape: T
func draw() -> String {
let lines = shape.draw().split(separator: "\n")
return lines.reversed().joined(separator: "\n")
}
}
let flippedTriangle = FlippedShape(shape: smallTriangle)
print(flippedTriangle.draw())
💻 출력 :
***
**
*
정확한 일반화 타입
을 노출struct JoinedShape<T: Shape, U: Shape>: Shape {
var top: T
var bottom: U
func draw() -> String {
return top.draw() + "\n" + bottom.draw()
}
}
let joinedTriangle = JoinedShape(top: smallTriangle, bottom: flippedTriangle)
print(joinedTriangle.draw())
💻 출력 :
*
**
***
***
**
*
JoinedShape<T: Shape, U: Shape>
구조체를 정의하는 것은 ‘뒤집힌 삼각형’을 다른 삼각형과 갖다 붙임으로써JoinedShape<Triangle, FlippedShape<Triangle>>
같은 타입이 되버림func max<T>(_ x: T, _ y: T) -> T where T: Comparable { ... }
struct Square: Shape {
var size: Int
func draw() -> String {
let line = String(repeating: "*", count: size)
let result = Array<String>(repeating: line, count: size)
return result.joined(separator: "\n")
}
}
func makeTrapezoid() -> some Shape {
let top = Triangle(size: 2)
let middle = Square(size: 2)
let bottom = FlippedShape(shape: top)
let trapezoid = JoinedShape(top: top, bottom: JoinedShape(top: middle, bottom: bottom))
return trapezoid
}
let trapezoid = makeTrapezoid()
print(trapezoid.draw())
func flip<T: Shape>(_ shape: T) -> some Shape {
return FlippedShaped(shape: shape)
}
func join<T: Shape, U: Shape>(_ top: T, _ bottom: U) -> some Shape {
JoinedShape(top: top, bottom: bottom)
}
let opaqueJoinedTriangles = join(smallTriangle, flip(smallTriangle))
print(opaqueJoinedTriangles.draw())
func invalidFlip<T: Shape>(_ shape: T) -> some Shape {
if shape is Square {
return shape // 에러: 반환 타입이 일치하지 않음
}
return FlippedShape(shape: shape) // 에러: 반환 타입이 일치하지 않음
}
struct FlippedShape<T: Shape>: Shape {
var shape: T
func draw() -> String {
if shape is Square {
return shape.draw()
}
let lines = shape.draw().split(separator: "\n")
return lines.reversed().joined(separator: "\n")
}
}
func `repeat`<T: Shape>(shape: T, count: Int) -> some Collection {
return Array<T>(repeating: shape, count: count)
}
func protoFlip<T: Shape>(_ shape: T) -> Shape {
return FlippedShape(shape: shape)
}
func protoFlip<T: Shape>(_ shape: T) -> Shape {
if shape is Square {
return shape
}
return FlippedShape(shape: shape)
}
let protoFlippedTriangle = protoFlip(smallTriangle)
let sameThing = protoFlip(smallTriangle)
protoFlippedTriangle == sameThing // 에러
protocol Container {
associatedtype Item
var count: Int { get }
subscript(i: Int) -> Item { get }
}
extension Array: Container { }
// 에러: '결합 타입' 을 가진 프로토콜은 반환 타입으로 사용할 수 없음
func makeProtocolContainer<T>(item: T) -> Container {
return [item]
}
// 에러: 'C' 를 추론하기 위한 충분한 정보가 없음
func makeProtocolContainer<T, C: Container>(item: T) -> C {
return [item]
}
func makeOpaqueContainer<T>(item: T) -> some Container {
return [item]
}
let opaqueContainer = makeOpaqueContainer(item: 12)
let twelve = opaqueContainer[0]
print(type(of: twelve))
// "Int" 를 인쇄합니다.