Opaque types - RaduG/swift_learning GitHub Wiki
Overview
Opaque types help hide the concrete type of an expression. The syntax uses the word some
.
Example:
protocol Shape {
associatedtype Color
var color: Color { get }
func copy() -> Self
func draw() -> String
}
struct Square: Shape {
let size: Int
let color: String
func draw() -> String {
var result = [String]()
for _ in 1...size {
result.append(String(repeating: "*", count: size))
}
return result.joined(separator: "\n")
}
func copy() -> Square {
return Square(size: size, color: color)
}
}
struct Triangle: Shape {
let size: Int
let color: Int
func draw() -> String {
var result = [String]()
for l in 1...size {
result.append(String(repeating: "*", count: l))
}
return result.joined(separator: "\n")
}
func copy() -> Triangle {
return Triangle(size: size, color: color)
}
}
struct JoinedShape<T: Shape, U: Shape>: Shape {
let top: T
let bottom: U
let color: Int = 0
func draw() -> String {
return "\(top.draw())\n\(bottom.draw())"
}
func copy() -> JoinedShape {
return JoinedShape(top: top, bottom: bottom)
}
}
func makeTrapezoid() -> Shape {
return JoinedShape(
top: Triangle(size: 3, color: 100),
bottom: Square(size:4, color: "FABFF13")
)
}
This code raises a compiler error because in makeTrapezoid
, the return type of Shape cannot be concretely determined as in itself is "generic" (because of Color and Self). Therefore, to solve the problem, the return value of makeTrapezoid
should be some Shape
, which means a concrete type of Shape
.
func makeTrapezoid() -> some Shape {
return JoinedShape(
top: Triangle(size: 3, color: 100),
bottom: Square(size:4, color: "FABFF13")
)
}
Functions returning opaque types can only return a single type. For example, this will cause a compile error:
func makeTrapezoid(size: Int) -> some Shape {
if size > 0 {
return JoinedShape(
top: Triangle(size: 3, color: 100),
bottom: Square(size:4, color: "FABFF13")
)
} else {
return Square(size: 1, color: "10")
}
}
error: function declares an opaque return type, but the return statements in its body do not have matching underlying types
func makeTrapezoid(size: Int) -> some Shape {