Previous translations have touched on extension many times, so explore the concept here.

Extensions that add new functionality to an existing class, enumeration, structure, or protocol type, even if the source code is not available. Extensions are similar to categories in Objective-C, but the extensions don’t have names. Using extensions you can do the following:

  • Add compute instance attributes and compute type attributes
  • Define instance methods and type methods
  • Provides a new initialization method
  • Define the subscript
  • Define and use a new nested type
  • Make existing types comply with the new protocol

You can also provide a default implementation for an existing Protocol, see Protocol Extensions.

Extensions can add new functions or provide default implementations, but cannot override existing functions

grammar

Add new functionality for type SomeType

extension SomeType {
    // new functionality to add to SomeType goes here
}
Copy the code

Extend multiple protocol implementations for type SomeType

extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}
Copy the code

Protocol Extension Adding Protocol Conformance with an Extension

The extension Extending a Generic Type is returned to the client

Conditionally add a function with a Generic Where Clause by extending the Generic type

Calculate attribute

We can add compute instance attributes and compute type attributes to existing types. We can add compute instance attributes to built-in Double types:

Extension Double {var km: Double {return self * 1_000.0} var m: Double {return self} var cm: Double {return self / 100.0} var mm: Double {return self / 1_000.0} var ft: Double {return self / 3.28084}} let oneInch = 25.4.mm print("One inch is \(oneInch) meters") // Prints "One inch is Meters "let threeFeet = 3. Ft print("Three feet is \(threeFeet) meters") // Prints "Three feet is 0.914399970739201 meters" let aMarathon = 42.km + 195.m print("A marathon is \(aMarathon) meters long") // Prints "A Marathon is 42195.0 meters long"Copy the code

You can add computed properties

Unable to store attributes, unable to add observers to existing attributes

Initialization method

Extensions can add new convenient initialization methods to existing types, using custom types as initialization method parameters for existing types, and using adapter patterns. But you can’t add a designated initializer or a de-initializer to a class. For details, see Initializer Delegation for Value Types.

Struct Size {var width = 0.0, height = 0.0} struct Point {var x = 0.0, Y = 0.0} struct Rect {var origin = Point() var size = size ()} let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: size (width: 5.0, height: 5.0)) extension Rect {init(center: Point, size: 5.0) Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origin: Point(x: OriginX, y: originY, size: size)}} let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: size (width: CenterRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)Copy the code

methods

Add instance methods and type methods through extensions to existing types. Add an instance method to Int:

extension Int { func repetitions(task: () -> Void) { for _ in 0.. <self { task() } } } 3.repetitions { print("Hello!" ) } // Hello! // Hello! // Hello!Copy the code

Mutating instance method

Instance methods can also modify the instance itself by mutating.

extension Int {
    mutating func square() {
        self = self * self
    }
}
var someInt = 3
someInt.square()
// someInt is now 9
Copy the code

The subscript

You can add subscripts to existing types by extension. Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int

  • 123456789 [0] returns 9
  • 123456789 [1] returns 8

… and so on:

extension Int { subscript(digitIndex: Int) -> Int { var decimalBase = 1 for _ in 0.. <digitIndex { decimalBase *= 10 } return (self / decimalBase) % 10 } } 746381295[0] // returns 5 746381295[1] // returns  9 746381295[2] // returns 2 746381295[8] // returns 7Copy the code

Out-of-bounds returns 0:

746381295[9]
// returns 0, as if you had requested:
0746381295[9]
Copy the code

Nested types

You can add new nested types to existing classes, structures, and enumerations by extending them:

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
}
Copy the code

Use the extension to add a new nested enumeration type Kind to Int that divides integers into three categories: positive, zero, and negative; Add a new count attribute kind.

func printIntegerKinds(_ numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .negative:
            print("- ", terminator: "")
        case .zero:
            print("0 ", terminator: "")
        case .positive:
            print("+ ", terminator: "")
        }
    }
    print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints "+ + - 0 - 0 + "
Copy the code

data

Docs.swift.org/swift-book/…