# Generic Swift learning

### 1 generic problem solving

###### The following is a non generic example
`Func swapTwoIntValue (inout a:Int, inout b:Int) {/ / use the inout keyword can modify the original numerical value. Let tempValue = a a = B B} = tempValue`
###### This function is used to exchange two numeric values
`Var oneInt = 3 var = twoInt = swapTwoIntValue (&, oneInt, b:, twoInt) print (oneInt, twoInt) = //oneInt = & = twoInt = 3 =`

### 2 generic functions

###### Here is a generic function
`Func SwapTwoValues < T> (inout a: T, inout T) {tempValue = a a = b b = tempValue}`
###### This function is similar to the example above, which is used to exchange two values of the same type, but this function uses the T placeholder instead of the actual type. No specific type is specified, but the incoming a, B must be of the same type T. When you call this function, you can specify the type of T that is specific. There is also the name of the function followed by the < T> is a function definition of a placeholder type name, and will not find the specific type of T
`SwapTwoValues (& oneInt, b: & twoInt (print) oneInt:/ (oneInt), twoInt:/ (twoInt) "/ / oneInt:3, twoInt:4) var oneStr =" hello "var twoStr =" world "SwapTwoValues (& b: & oneStr, twoStr) print (oneStr:/ (oneStr), twoStr:/ (twoStr)" twoStr:hello var / / oneStr:world), oneDouble = 10.01 var twoDouble = 20.02 SwapTwoValues (& oneDouble, b: & twoDouble (print) oneDouble:/ (oneDouble), twoDouble:/ (twoDouble) "/ / oneDouble:20.02, twoDouble:10.01)`

### 5 generic types

###### The following shows a non generic version of the stack
`Struct IntStack{var items = [Int] (mutating func push) / / stack (item:Int) {items} / /.Append (item) mutating (POP) func stack -> Int{return (items.removeLast)}}`
###### This is a generic version of the stack
`Struct Stack< Element> items) {var = [Element] (mutating func push (item:Element) {items.append} (item) mutating func pop (->); Element{return (items.removeLast)}}`
###### First add &lt to the name of the function; the generic type name > < > which indicates the type parameter name. And then do the same function as a non generic stack in the function body. This generic structure is not only the value of the stack Int type, can also be other types
`Var stack = Stack< String> (<) / / add following the type name; type name > stack.push ("uno") stack.push ("Dos") stack.push ("tres") stack.push ("Cuatro") (print) (stack.pop) / / Cuatro`

### 6 extend a generic type

###### You can extend a generic type to add properties, methods, indexes, etc..
`Extension Stack{/ / Stack to the generic extension of a computing type attribute topItem, return to the top of the item var topItem:Element? Return items.isEmpty nil {items[items.count-1]}}?: Print ("stack's top item is: / (stack.topItem!)") //stack's top item is: Tres`

### 7 type constraint

###### You can add a type or protocol name to the name of the type parameter, separated by a colon, separated by a number of types
`Func somFuntion< C:SomeClass, P:SomeProtocol> (someClass:C, someProtocol:P) {}`

#### Type constraint practice

###### This non generic type method is used to find whether a string is in an array of characters, and there is a return of index
`Func findStrInArray (array:[String], strToFind:String) -> Int? {for (index, value) in (array.enumerate) {if strToFind = = value{return index return nil}}}`
###### The following is a generic version of the above non generic method
`Func findIndex < (array:[S]; S:Equatable> -> Int valueToFind:S, _)? {for (index, value) in (array.enumerate) {if value = = valueToFind {/ / if S:Equatable did not specify this sentence would be compiled by return index return nil}}}`
###### In the generic case, not all types can be used to compare the = = all constraints, you must specify a generic type parameter for Swift Equatable protocol, which means that the type S must be representative of the support of Equatable protocol. All Swift standard types are supported by the Equatable protocol by default
`Let value = findIndex ([3.14159, 0.1, 0.25], 9.3) / / doubleIndex type Int?, its value is nil, because 9.3 is not in the array let stringIndex = findIndex ("" Mike "," Malcolm "," Andrea "," Andrea ") / / stringIndex type is Int, its value is? 2`

### 8 association type

#### Relevance type practice

###### The following defines a protocol that specifies an associated type
`Protocol Container{typealias itemType / / declare a type of association mutating func append (item:itemType) var count:Int{get} subscript (i:Int) -> itemType {get};}`
###### The following is a non generic version of the adoption of the Container protocol
`Struct intStack: Container {/ / IntStack of the original implementation of items = [Int] (part of VaR) mutating func push (item: Int) {items.append} (item) mutating func pop (->); Int (items.removeLast) {return} / / Container protocol typealias ItemType mutating = Int func append (item: Int) {self.push (item var count: Int return)} {items.count} subscript (i: Int) -> Int return {items[i]}};`
###### Here is a generic version of the
`Struct genericStack< Element>: Container{; / / genericStack< Element> the original items = [Element] (VaR part) mutating func push (item: Element) {items.append} (item) mutating func pop (->); Element (items.removeLast) {return} / / Container protocol typealias ItemType mutating func append (item: = Element Element self.push (item)) {var} count: {return} Int items.count subscript (i: Int) -> Element return {items[i]}};`

#### Specify an association type by extending an existing type

###### Swift in Array has met the requirements of the Container protocol, which means that the Array can be extended to adopt the Container protocol, you can achieve this by an empty extension
`Extension Array: Container{}`

#### Where clause

###### The following example determines whether the two elements of the Container protocol are all elements of the same order and value.
`Func allItemsMatch< C1:Container, C2:Container where C1.itemType (someContainer:C1 = = C2.itemType, C1.itemType:Equatable> anotherContainer:C2, _) -> Bool{if someContainer.count anotherContainer.count{return false for}! = I in 0... SomeContainer.count-1{if someContainer[i] anotherContainer[i]{return false! = return true}}}`
###### The generic function to add a where clause in the type parameter constraints, inside C1, C2 must be adopted type Container protocol, and a generic type C1, C2 must be the same, but the generic type C1 must be adopted Equatable.
`Var stackOfStrings = genericStack< String> (stackOfStrings.append) ("uno") stackOfStrings.append ("Dos") stackOfStrings.append ("tres") var arrayOfStrings = ["uno", "Dos", "tres"] type //array to meet the Container type, the above extension Array if allItemsMatch reference (stackOfStrings, arrayOfStrings) {print ("All items match.")} else {print ("Not all items match.")} / / the result is: All items match.`