In swift, extension is somewhat similar to the category of objective-c, but extension is more powerful and flexible than category, and it can extend not only the method of a certain type or struct, It can also be used in conjunction with protocol, to write more flexible and powerful code. 0. Overview-Extension Summary
In swift, Swift can add new features for a specific class, Strut, enum, or protocol. When you do not have permission to transform the source code, you can extend the type by extension. Extension is somewhat similar to the category of OC, but slightly different is that category has a name, and extension has no name.
Swift's extension can do several things, add a calculated attribute-computed Properties Add Method-Methods Add initialization Method-initializers Add satellite script-subscripts Add and use nested types -nested types follows and implements a protocol-conform protocol
In Swift, you can even extend a protocol protocol, implement its Protocol method, or add additional functionality so that the type of the protocol can be used, in Swift, which is called the Protocol Extension-Protocol extension, which is illustrated in the following.
Note: Extension can add a new attribute to a type, but it cannot overwrite an existing attribute. For example animal already has a eat method, we cannot use extension to override animal eat method. 1. Grammar-Extension Syntax
The syntax for defining extension is very simple, just use the extension keyword, the following code,
Extension SomeType {
//new functionality to add to SomeType goes here
}
Extension can let a particular type implement one or more protocols, meaning that one or more protocols can be implemented for types such as class, structure, or enum, as shown in the following code.
Extension Sometype:someprotocol, Anotherprotocol {
//implementation of protocol requirements goes here
}
The above code represents a simple function, that is, SomeType obey the Someprotocol and Anotherprotocol protocol, and implement the methods in the two protocols, we can make a simple split of the above code, so that the code is more concise and easy to read, the following code,
Extension Sometype:someprotocol {
//Implentations of Someprotocol
}
extension Sometype:anotherprotocol {
//Implentations of Anotherprotocol
}
2. Add multiple features
In the previous list, extension can add a number of features to a type, following a simple explanation, and an example. 2.1 Adding a calculated attribute-computed properties
Extension can add a computed property (computed properties) for a type that already exists, the following demo adds 5 calculated properties for the swift built-in double type, km, m, cm, MM, ft, The function used to provide the basis for calculating distances, as shown in the following code,
Extension Double {
var km:double {return self * 1_000.0}
var m:double {return self}
var cm:double {ret Urn self/100.0}
var mm:double {return self/1_000.0}
var ft:double {return self/3.28084}
}
// Usage of Double extension let
oneinch = 25.4.mm
print ("one inch are \ (oneinch) meters")
//Prints "one inch is 0.0254 meters "let
threefeet = 3.ft
print (" Three feet are \ (threefeet) meters ")
//Prints" three feet is 0.9 14399970739201 meters "
What is a computed property? This is probably the feature of Swift language, there are two types of properties in Swift, one is the storage property and the other is the computed attribute. A stored property is a constant or variable stored in a particular class, a struct, you can specify a default value when you define a stored property, or you can set or modify the value of a stored property during construction, and be aware that the attribute is not defined in the enum, and the computed attribute does not store the value directly. Instead, provide a getter, setter to indirectly get and set the values of other properties and variables.
To summarize, the difference between stored and computed properties in Swift is the following table,
Store Properties |
Calculated Properties |
Store constants or Variable properties |
Used to calculate values, not to store values |
defined in class, struct |
defined in class, struct, enum |
In the demo above, these computed properties indicate that a double value should be treated as a specific unit of length, that is, kilometers, meters, centimeters, millimeters, and so on. Although they are implemented as calculated properties, these property names can be placed behind floating-point values through the. operator. A double-type floating-point value of 1.0 means "one meter", which is why. The M computed property returns the double value itself. Similarly, 1 meters is approximately equal to 3.28084 inches (feet), so the FT calculates the attribute to convert to "M" when it needs to be multiplied by 3.28084.
These properties are all read-only (read-only) computed properties, so for convenience, you only need to use the GET keyword when defining them, but for brevity and intuition, the demo directly omits the Get keyword. The return value of these computed properties is a double type, so you can use it in any place where the double type applies, such as the following code,
Let Amarathon = 42.km + 195.m
print ("A marathon are \ (Amarathon) meters long")
//Prints "A marathon is 42195.0 met ERs Long "
Note: Extension can add calculated properties, but cannot add storage properties or add observers for the current property. 2.2 Adding constructors-initializers
Extension can add a convenient initialization method for a class that already exists. This allows you to extend the other types so that the type can accept your custom type as an initialization parameter at initialization, adding an additional initialization method to the type, providing more choices when creating objects of that type.
The following example defines a struct type rect, which represents a rectangular geometry, and we also define two other struct types, size and point, all of which have 0.0 default values set. As the following code shows,
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect { C6/>var origin = point ()
var size = size ()
}
Because the struct RECT provides default values for all of its properties, it automatically has a default initialization method and a member-by-one (memberwise) initialization method, which we can use to create an instance of the rect struct body, as in the following code,
Let Defaultrect = rect () let
memberwiserect = Rect (Origin:point (x:2.0, y:2.0), Size:size (width:5.0, height:5.0) )
Now we can add an additional initialization method to the struct rect by extension, which takes a point and size as a parameter, the following code,
Extension Rect {
init (center:point, size:size) {let
Originx = center.x-(SIZE.WIDTH/2) let
originy = cen Ter.y-(SIZE.HEIGHT/2)
self.init (Origin:point (X:originx, Y:originy), size:size)
}
}
The logic of this custom initialization method implementation is not complex, first it is computed by passing in the point parameter Center and size parameter size (Originx, Originy), and then invoking the struct's one-member initialization method, the Init (origin:size :), the initialization method stores the origin and size parameters in the corresponding property, as shown in the following code.
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)
Note: If you use extension to add an initialization method, you also need to ensure that each of its properties is fully initialized at the end of the initialization method for that type. 2.3.1 Add Method-Methods
Similar to the OC category, with extension, you can add instance methods (instance method) and type methods to a type, and the following code adds an instance method named repetitions to the int type.
Extension Int {
func repetitions (Task: ()-Void) {for
_ in 0..<self {
task ()}}
}
The new repetitions (task:) method takes a closure ()->void as a parameter, and the closure acts as a function, and the function has no entry and return values.
Let's take a simple test, as shown in the following code,
3.repetitions {
print ("hello!")
}
Hello!
Hello!
Hello!
2.3.2 Adding mutation Methods-mutating method
An instance method added through extension can also modify (modify) or mutate (mutate) The instance itself, if the method defined by the struct and the enumeration wants to change itself or its own properties, then the instance method must be marked as mutated (mutating).
The following example adds a mutation method named Square to the int type, which is used to calculate the square of the original value, as shown in the following code.
Extension Int {
mutating func square () {Self
= self * Self
}
}
var someint = 3
Someint.squa Re ()
//Someint is now 9
Here for the mutating keyword again, if we delete the mutating keyword, the compiler will error, only mutating modified method to change the instance properties and the instance itself, mutating keyword and extension, With protocol, you can implement more complex functions with more concise code. The author suggests that readers search for materials, write demos, deepen impressions and understand. 2.4 Adding a satellite script-subscripts
Extension can add a satellite script subscript for a particular type. So what is a subordinate script? A subordinate script can be defined in class, struct, enum, which can be thought of as a shortcut to access an object, a collection, or a sequence, and does not require a specific assignment method and access method in the calling instance. For example, accessing an element in an array instance with a subordinate script can be written as Somearray[index], and accessing the elements in the dictionary instance can be written as Somedictionary[key], which the reader may have noticed, Accessing the array and dictionary elements in siwft in this shortcut is often used, so it can be inferred that Swift has already defaulted on the features of the affiliate script for the developer.
The following example adds an integer subscript to the secondary script for the int type, [n] Returns the number of the nth digit of the number corresponding to the decimal (decimal), and of course the counting method starts at the far right, for example, 123456789[0] returns 9, and 123456789[1] returns 8. The specific implementation of this method is shown in the following code,
extension int {
subscript (digitindex:int), int {
var decimalbase = 1 for
_ in 0..<digitindex {
de Cimalbase *=
}
return (self/decimalbase)%}
746381295[0]
//returns 5
746381295 [1]
Returns 9
746381295[2]
//returns 2
746381295[8]
//returns 7
Careful analysis of the subscript method, the implementation of the logic is actually a pupil's exercises, here do not repeat.
If an int number does not have enough digits, it will add a total of 0 to the left and then return to the caller with the following code,
746381295[9]
//returns 0, as if you had requested:
0746381295[9]
2.5 Adding nested types-Nested types
Extension can add nested types for Class (class), struct (structure), and enumeration (Enumation), as in the following code,
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
}
}< c13/>}
The above demo adds a nested enumeration type to int, which is named kind, which is used to indicate whether a number is a positive, plural, or 0, because it is nested because the enumeration is defined inside the extension of Int. (Here, I may have an incorrect understanding of nesting, and this understanding is reserved for the time being, and the reader is welcome to correct it.) )
The demo also adds a computed attribute (computed property) to int, named Kind, which returns. Zero,. Positive, or. Negative, respectively, for numeric values.
The nested enumeration type can now be used in any int value, as shown in the following code.
Func Printintegerkinds (_ Numbers: [Int]) {for number in
numbers {
switch number.kind {case
. Negative:
P Rint ("-", Terminator: "") Case
. Zero:
print ("0", Terminator: "") Case
. Positive:
print ("+", Terminator: "")
}
}
print ("")
}
printintegerkinds ([3, -27, 0, 6, 0, 7])
//Prints "+ +- 0-0 + "
The code above is easy to understand, Printintegerkinds (_:) takes an array of type int and then iterates through the array and judges the kind of each element to determine whether the array element is positive, negative, or 0, the code is simple and does not explain much. 3. Reference link Apple documents-extensions siwft Properties