Latest web development tutorials

Swift Generics

Swift offre una soluzione flessibile generico e permette di scrivere funzioni riutilizzabili e tipi.

libreria standard Swift è costruito da codice generico.

array Swift e tipi di dizionari sono generico insieme.

È possibile creare un array Int, è possibile creare un array di stringhe, o anche array di dati può essere di qualsiasi tipo di altra Swift.

Il seguente esempio è uno scambio funzione non generico per lo scambio dei due valori Int:

// 定义一个交换两个变量的函数
func exchange(inout a: Int, inout b: Int) {
    let temp = a
    a = b
    b = temp
}

var numb1 = 100
var numb2 = 200

print("交换前数据: \(numb1) 和 \(numb2)")
exchange(&numb1, b: &numb2)
print("交换后数据: \(numb1) 和 \(numb2)")

L'output sopra l'esecuzione del programma è il seguente:

交换前数据: 100 和 200
交换后数据: 200 和 100

funzioni generiche possono accedere a qualsiasi tipo, come ad esempio Int o una stringa.

L'esempio che segue è una funzione generica per lo scambio di swap due valori Int e stringa:

func exchange<T>(inout a: T, inout b: T) {
    let temp = a
    a = b
    b = temp
}

var numb1 = 100
var numb2 = 200

print("交换前数据:  \(numb1) 和 \(numb2)")
exchange(&numb1, b: &numb2)
print("交换后数据: \(numb1) 和 \(numb2)")

var str1 = "A"
var str2 = "B"

print("交换前数据:  \(str1) 和 \(str2)")
exchange(&str1, b: &str2)
print("交换后数据: \(str1) 和 \(str2)")

L'output sopra l'esecuzione del programma è il seguente:

交换前数据:  100 和 200
交换后数据: 200 和 100
交换前数据:  A 和 B
交换后数据: B 和 A

versione generica di questa funzione utilizzando il nome del tipo di segnaposto (di solito indicato con la lettera T in questo caso) al posto dei nomi tipo effettivo (come int, String o doppio). Segnaposto nome di tipo non deve suggerire che tipo T, ma suggerisce A e B devono essere dello stesso tipo T, indipendentemente dal tipo T rappresenta. Solo scambio (_: _ :) funzione quando passò in ogni tipo di chiamata al fine di determinare il tipo effettivo T rappresenta.

Un'altra differenza è che questo nome della funzione quest'ultima seguita dal nome generico del tipo di segnaposto (T) è racchiuso tra parentesi angolari ( ). Le parentesi angolari detto Swift che T è lo scambio (_: _ :) funzione del tipo definito. Poiché T è un tipo segnaposto nome, Swift non è trovare il nome del tipo T. effettiva


tipo generico

Swift consente di definire i propri tipi generici.

classi personalizzate, strutture e enumerazioni applicate a qualsiasi tipo Array e l'uso di dizionario.

struct TOS<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
}

var tos = TOS<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
print(tos.items)

tos.push("类型参数")
print(tos.items)

tos.push("类型参数名")
print(tos.items)


let deletetos = tos.pop()

L'output sopra l'esecuzione del programma è il seguente:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "类型参数"]
["Swift", "泛型", "类型参数", "类型参数名"]

tipo generico estesa

Quando si estende un tipo generico di tempo (estensione utilizzando parole chiave), non è necessario fornire una lista di parametri di tipo nella definizione estesa. Più conveniente è quella primitiva parametro di tipo definizione tipo dichiarato nella lista può essere ampliata in uso e i nomi dei parametri del tipo di originale viene utilizzata come riferimento per la definizione originale del parametro type.

Esempi

L'esempio seguente estende il tipo TOS generica, per aggiungere una proprietà di sola lettura di nome primo calcolo, verrà restituito l'attuale top degli elementi dello stack e non verrà rimossa dalla pila.

struct TOS<T> {
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
}

var tos = TOS<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
    print(tos.items)
    
    tos.push("类型参数")
    print(tos.items)
    
    tos.push("类型参数名")
    print(tos.items)

// 扩展泛型 TOS 类型
extension TOS {
    var first: T? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

if let first = tos.first {
    print("栈顶部项:\(first)")
}

L'output sopra l'esecuzione del programma è il seguente:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "类型参数"]
["Swift", "泛型", "类型参数", "类型参数名"]
栈顶部项:类型参数名

tipo vincolo

Tipo di vincolo specifica che un parametro di tipo deve ereditare dalla classe specificata o seguire un protocollo o composizione specifica.

sintassi vincolo Tipo

È possibile scrivere un vincolo di tipo nella parte posteriore di un tipo di nomi di parametro, divise da due punti, come parte della catena parametro type. Tali atti sulla base del tipo di sintassi di vincolo per funzioni generiche sono le seguenti (dello stesso tipo generico di sintassi):

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // 这里是函数主体
}

Esempi

// 函数可以作用于查找一字符串数组中的某个字符串
func findStringIndex(array: [String], _ valueToFind: String) -> Int? {
    for (index, value) in array.enumerate() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}

let strings = ["cat", "dog", "llama", "parakeet", "terrapin"]
if let foundIndex = findStringIndex(strings, "llama") {
    print("llama 的下标索引值为 \(foundIndex)")
}

L'output sopra l'esecuzione del programma è il seguente:

llama 的下标索引值为 2

Esempi del tipo di associazione

typealias Swift parola chiave utilizzata per impostare il tipo di associazione.

Definire un protocollo, a volte dichiarano uno o più associati tipo di pezzo di protocollo della definizione è molto utile in quanto.

protocol Container {
    // 定义了一个ItemType关联类型
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

// 遵循Container协议的泛型TOS类型
struct TOS<T>: Container {
    // original Stack<T> implementation
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
    
    // conformance to the Container protocol
    mutating func append(item: T) {
        self.push(item)
    }
    
    var count: Int {
        return items.count
    }
    
    subscript(i: Int) -> T {
        return items[i]
    }
}

var tos = TOS<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
print(tos.items)

tos.push("参数类型")
print(tos.items)

tos.push("类型参数名")
print(tos.items)

L'output sopra l'esecuzione del programma è il seguente:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "参数类型"]
["Swift", "泛型", "参数类型", "类型参数名"]

dove dichiarazioni

Il tipo di vincolo per garantire la conformità con la definizione del tipo di vincolo funzione generica o classe.

È possibile definire i parametri della dichiarazione in cui il vincolo nella lista dei parametri.

Dove si può scrivere una dichiarazione, seguita da l'elenco dei parametri di tipo nella parte posteriore, dove la dichiarazione è seguita da uno o più tipi di vincoli per l'associazione, e (o) l'equivalente di uno o più tipi e tipi di associazione tra rapporto (uguaglianza).

Esempi

L'esempio seguente definisce una funzione generica denominata allItemsMatch, utilizzato per verificare se due istanze di container contiene gli stessi elementi nello stesso ordine.

Se tutti gli elementi possono abbinare, per poi tornare ad un valore booleano true, altrimenti è falsa.

protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct Stack<T>: Container {
    // original Stack<T> implementation
    var items = [T]()
    mutating func push(item: T) {
        items.append(item)
    }
    
    mutating func pop() -> T {
        return items.removeLast()
    }
    
    // conformance to the Container protocol
    mutating func append(item: T) {
        self.push(item)
    }
    
    var count: Int {
        return items.count
    }
    
    subscript(i: Int) -> T {
        return items[i]
    }
}

func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, anotherContainer: C2) -> Bool {
        // 检查两个Container的元素个数是否相同
        if someContainer.count != anotherContainer.count {
            return false
        }
        
        // 检查两个Container相应位置的元素彼此是否相等
        for i in 0..<someContainer.count {
            if someContainer[i] != anotherContainer[i] {
                return false
            }
        }
        // 匹配所有项,返回 true
        return true
}

var tos = Stack<String>()
tos.push("Swift")
print(tos.items)

tos.push("泛型")
print(tos.items)

tos.push("Where 语句")
print(tos.items)

var eos = ["Swift", "泛型", "Where 语句"]
print(eos)

L'output sopra l'esecuzione del programma è il seguente:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "Where 语句"]
["Swift", "泛型", "Where 语句"]