Generic code allows you to write functions and types that are flexible and reusable according to your own needs and that are suitable for any type. It allows you to avoid repetitive code and to express the intent of the code in a clear and abstract way.
Generics are one of the powerful features of Swift, and many of the Swift standard libraries are built from generic code. In fact, the use of generics runs through the entire language manual, but you don't find it. For example, Swift's array and dictionary types are generic sets. You can create an int array, or you can create a string array, or even a type data array of any other Swift. Similarly, you can create dictionaries (dictionary) that store any of the specified types, and these types can be unlimited.
Problems solved by generics
Here is a standard, non-generic function swaptwoints, which is used to exchange two INT values:
Func swaptwoints (inout a:int, inout b:int) {
Let Temporar ya = a
a = b
B = Temporarya
}
This function uses the write read out (in-out) parameter to exchange the values of A and B
swaptwoints function can exchange the original value of B to a, you can also exchange A's original value to B, you can Call this function to exchange the value of two int variables:
var someint = 3
var anotherint = 107
Swaptwoints (&someint, &anotherint)
println ("Someint is now (Someint), and Anotherint are now (anotherint)") The
//output "Someint is now 107, and Anotherint are now 3"
Swaptwoints function is very useful, but it can only exchange int values, if you want to exchange two string or double, you have to write More functions, such as swaptwostrings and Swaptwodoublesfunctions, are as follows:
Func swaptwostrings (inout a:string, inout b:string) {
L ET Temporarya = a
A = b
B = Temporarya
}
Func swaptwodoubles (inout a:double, inout b:double) {
Let Temporarya = a
A = b
b = Temporarya
}
You may notice that the swaptwoints, swaptwostrings, and swaptwodoubles functions are the same, except that the variable types that are passed in are different, int, string, and double, respectively.
But the practical application usually requires a more powerful and, as far as possible, the flexibility of a single function that can be used to exchange two of any type of value, fortunately, generic code helps you solve this problem.
Note: In all three functions, the type of A and B is the same. If A and B are not the same type, then they cannot exchange values. Swift is a type-safe language, so it does not allow a variable of type string and a variable of type double to exchange values with each other. If you do, Swift will report a compilation error.
Generic functions
A generic function can work on any type, here is a generic version of the above swaptwoints function, which is used to exchange two values:
Func swaptwovalues (inout a:t, inout b:t) {
Let Temporarya = a
A = b
b = Temporarya
}
The Swaptwovalues function body and the swaptwoints function are the same, and it is only a little bit different from the swaptwoints in the first line, as follows:
Func swaptwoints (inout a:int, InOut b:int)
Func swaptwovalues (inout a:t, InOut b:t)
The generic version of this function uses the name of the placeholder type (usually denoted by the letter T in this case) instead of the actual type name (such as int, string, or double). The placeholder type name does not indicate what type T must be, but it suggests that A and b must be of the same type T, regardless of what type T represents. Only the actual type that the Swaptwovalues function passes in each invocation determines the type that T represents.
Another difference is that the placeholder type name (T) followed by the generic function name is enclosed in angle brackets (). This angle bracket tells Swift that T is a type defined by the Swaptwovalues function. Because T is a placeholder-named type, Swift does not look for the actual type named T.
The Swaptwovalues function can also be called as a swaptwoints function in addition to requiring that two of any type values passed in are the same type. Each time swaptwovalues is called, the type value represented by T is passed to the function.
In the following two examples, T represents int and string, respectively:
var someint = 3
var anotherint = 107
Swaptwovalues (&someint, &anotherint)
Someint is now 107, and Anotherint are now 3
var somestring = "Hello"
var anotherstring = "World"
Swaptwovalues (&somestring, &anotherstring)
Somestring is now "world", and anotherstring are now "Hello"
Note that the function Swaptwovalues defined above is inspired by the swap function. The swap function exists in the Swift standard library and can be used arbitrarily in other classes. If you need a function like the Swaptwovalues function in your code, you can use the SWAP function that already exists.
Type parameter
In the swaptwovalues example above, the placeholder type T is an example of a type parameter. The type parameter is specified and named as a placeholder type, followed by a pair of angle brackets (such as), immediately following the function name.
Once a type parameter is specified, it can be used to define a function's parameter type (such as parameters A and B in the Swaptwovalues function), or as a function return type, or as a comment type in the body of a function. In this case, the placeholder type represented by the type parameter is replaced by the actual type whenever the function is called (in the swaptwovalues example above, when the function is first called, T is replaced by int, and the second call is replaced by a string. )。
You can support multiple types of parameters, named in angle brackets, separated by commas.
Named type parameters
In a simple case, a generic function or generic type needs to specify a placeholder type (such as the swaptwovalues generic function above, or a generic set that stores a single type, such as an array), and typically uses a single letter T to name the type parameter. However, you can use any valid identifier as the name of the type parameter.
If you use more than one parameter to define more complex generic functions or generic types, it is useful to use more descriptive type parameters. For example, the Swift dictionary (Dictionary) type has two type parameters, one is the key and the other is a value. If you write your own dictionary, you might define these two types of parameters as KeyType and ValueType to remember their role in your generic code.
Note Always use camel-named methods (such as T and KeyType) that begin with uppercase letters to name the type parameters to indicate that they are placeholders for types, not type values.
Generic type
Typically in generic functions, Swift allows you to define your own generic type. These custom classes, structs, and Enumerations Act on any type, as is the use of array and dictionary.
This section shows you how to write a generic set-type –stack (stack). A stack is a collection of a range of ranges, similar to an array, but it is a more restrictive collection than the array type of Swift. An array can allow the Insert/delete operation anywhere inside it, and the stack, which only allows adding new items at the end of the collection (like pushing a new value into the stack). The same stack can only be removed from the end (as if the pop is a value out of the stack).
Note that the concept of stacks has been used by the Uinavigationcontroller class to emulate the navigation structure of the controller. You add (add) a new attempt controller to the navigation stack by calling Uinavigationcontroller's pushviewcontroller:animated: Method, and through popviewcontrolleranimated: method to remove (pop) an attempt controller from the navigation stack. Whenever you need a strict LIFO method to manage the collection, the stack is the most practical model.
Shows the behavior of a stack's push/stack (POP):
1. 现在有三个值在栈中;2. 第四个值“pushed”到栈的顶部;3. 现在有四个值在栈中,最近的那个在顶部;4. 栈中最顶部的那个项被移除,或称之为“popped”;5. 移除掉一个值后,现在栈又重新只有三个值。
Here is how to write a non-generic version of the stack, int value type stack:
struct IntStack {
var items = Int
mutating func push (Item:int) {
Items.append (item)
}
Mutating func pop (), Int {
Return Items.removelast ()
}
}
This struct uses an array-nature items store value in the stack. Stack provides two methods: Push and pop, pressing a value from the stack and removing a value. These methods are marked as mutable, because they need to modify (or transform) the items array of the struct body.
The IntStack type shown above can only be used for int values, but it is useful to define a generic stack class (a stack that can handle any type of value).
Here is a generic version of the same code:
struct Stack {
var items = T
mutating func push (item:t) {
Items.append (item)
}
Mutating func pop (), T {
Return Items.removelast ()
}
}
Note that the generic version of the stack is basically the same as the non-generic version, but the generic version of the placeholder type parameter is T instead of the actual int type. This type parameter is contained in a pair of angle brackets (), immediately following the struct name.
T defines a node named "some type T" to be provided for later use. This type of future can be represented as "T" anywhere in the definition of the struct. In this case, T is used as a node in the following three places:
? Creates a property named items that initializes it with an array of empty t-type values;
? Specifies a push method that contains a parameter named item, which must be of type T;
? Specifies the return value of a pop method, which will be a value of type T.
When creating a new singleton and initializing it, by writing the actual specified stack with a pair of angle brackets immediately following the type name, create a stack instance that is the same as creating the array and dictionary:
var stackofstrings = Stack ()
Stackofstrings.push ("Uno")
Stackofstrings.push ("DOS")
Stackofstrings.push ("Tres")
Stackofstrings.push ("cuatro")
Now the stack already has 4 strings.
will show stackofstrings how to push these four values into the stack:
POPs from the stack and removes the value "cuatro":
Let Fromthetop = Stackofstrings.pop ()
Fromthetop is equal to ' cuatro ', and the stack now contains 3 strings
Shows the process of how to pop a value from a stack:
Because the stack is a generic type, it can be used in Swift to create stacks of any valid type, like arrays and dictionary.
Type constraints
The Swaptwovalues function and the stack type can work on any type, but sometimes it is useful to enforce constraints on types that are used on generic functions and generic types for a particular type. A type constraint specifies a type parameter that must inherit from the specified class, or follows a specific protocol or protocol composition.
For example, the dictionary type of Swift makes some restrictions on the type of key that is acting on it. In the dictionary's description, the key type of the dictionary must be hashed, that is, there must be a way to make it a unique representation. Dictionary needs its key to be hashed so that it checks to see if it already contains a value of a particular key. Without this requirement, dictionary will not tell whether to insert or replace the value of a particular key, nor can it find the given key value that has been stored in the dictionary.
This requirement enforces a type constraint on the dictionary key, and of course its key type must follow the Hashable protocol (a specific protocol defined in the Swift standard library). All Swift basic types (such as String,int, double, and Bool) are hashed by default.
When you create custom generic types, you can define your own type constraints, which, of course, support most of the powerful features of generic programming. Abstract concepts such as hash-based type characteristics are defined by their conceptual characteristics, rather than by their direct type characteristics.
Type constraint syntax
You can write a type constraint that follows a type parameter name, separated by a colon, as part of the chain of type parameters. The underlying syntax for a type constraint that acts on a generic function is as follows (and the syntax for a generic type is the same):
Func someFunction
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Swift-Learning generics