introduce
Extensions can add new functionality to classes, structures, enums, and protocols. Including the ability to extend types without source code access. The concept of extension and Objective-C classification is similar. (The Swift extension does not have a name, unlike the Objective-C classification).
In Swift, extensions can do:
- Add calculated instance attributes and calculated type attributes
- Define instance methods and type methods
- Provide a new initializer
- Define subscript
- Define and use new nested types
- Make existing types consistent with protocols
It is worth noting:Extensions can add functionality to types, but existing functionality cannot be rewrited.
Extended syntax
Use the keyword extension to define extensions:
extension SomeType { // new functionality to add to SomeType goes here }
Extensions can extend existing types so that they can adapt to one or more protocols:
extension SomeType: SomeProtocol, AnotherProtocol { // implementation of protocol requirements goes here }
Calculate properties
Extensions can add compute instance attributes and compute type attributes to existing 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. print("One inch is \(oneInch) meters") // Prints "One inch is 0.0254 meters" let threeFeet = print("Three feet is \(threeFeet) meters") // Prints "Three feet is 0.914399970739201 meters"
Since these properties are read-only computed properties, they do not need to add keyword get.
Can perform operations directly:
let aMarathon = + print("A marathon is \(aMarathon) meters long") // Prints "A marathon is 42195.0 meters long"
It is worth noting:Extensions can add new computed properties, but they cannot add storage properties, or add property observers for existing properties.
Initializer
Extensions can add new convenience initializers to classes, but they cannot add new specified initializers or deinitializers to classes. The specified initializer and deinitializer must always be provided by the original class implementation.
The following defines several structures:
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() }
We can create a Rect instance like this (for the default initializer, you can view the initialization section):
let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))
At this time, we can expand the Rect structure and add a new initializer to it:
extension Rect { init(center: Point, size: Size) { let originX = - ( / 2) let originY = - ( / 2) (origin: Point(x: originX, y: originY), size: size) } }
Then we can use the new initialization method to create the instance:
let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0)) // centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
method
Here is a method called repetitions for the Int type:
extension Int { func repetitions(task: () -> Void) { for _ in 0..<self { task() } } }
Then we can call this method like this:
{ print("Hello!") } // Hello! // Hello! // Hello!
Mutation instance method
The instance method with the addition of an extension can also modify (or mutate) the instance itself. Modifying the structure and enumeration methods of self or its properties must mark the instance method as mutating, just like the mutated method in the original implementation.
As in the following example:
extension Int { mutating func square() { self = self * self } } var someInt = 3 () // someInt is now 9
Subscript
Want to achieve
- 123456789[0] Return 9
- 123456789[1] Return 8
The code is as follows:
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 7
If the subscript goes beyond the bounds, return 0:
746381295[9] // returns 0, as if you had requested: 0746381295[9]
Nested Types
Extend to add nested types:
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 } } }
Nested types can now be used in any Int value:
func printIntegerKinds(_ numbers: [Int]) { for number in numbers { switch { 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 + "
Refer to the original English text:
/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/#//apple_ref/doc/uid/TP40014097-CH24-ID151
Summarize
The above is the entire content of this article. I hope that the content of this article will be of some help to everyone’s learning or using Swift. If you have any questions, you can leave a message to communicate. Thank you for your support.