Reading — step 1 of 6
Learn
~1 min readClosures and Generics
Generics parameterize types and functions over types:
func swap<T>(_ a: inout T, _ b: inout T) {
let tmp = a
a = b
b = tmp
}
struct Stack<Element> {
private var items: [Element] = []
mutating func push(_ x: Element) { items.append(x) }
mutating func pop() -> Element? { items.popLast() }
}
where clauses add constraints:
func largest<T: Comparable>(_ a: [T]) -> T? {
a.max()
}
func allEqual<T: Equatable>(_ a: [T]) -> Bool where T: Hashable {
Set(a).count <= 1
}
Protocols are interfaces — types declare conformance:
protocol Shape {
func area() -> Double
}
struct Circle: Shape {
let radius: Double
func area() -> Double { 3.14 * radius * radius }
}
Protocol extensions — provide default implementations:
extension Shape {
func describe() -> String { "area: \(area())" }
}
Now every Shape has describe() automatically — they only need to implement area(). This is Swift's main alternative to inheritance.
Protocol composition:
func process<T: Shape & CustomStringConvertible>(_ x: T) { ... }
Existential types with any:
let shapes: [any Shape] = [Circle(radius: 5), Square(side: 3)]
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…