Latest web development tutorials

Swift genéricos

Swift proporciona una solución flexible genérico y le permite escribir funciones reutilizables y tipos.

biblioteca estándar Swift se construye a cabo por código genérico.

Swift matrices y tipos de diccionarios son conjunto genérico.

Puede crear una matriz Int, puede crear una matriz de cadenas, o incluso matriz de datos puede ser cualquier tipo de otra Swift.

El siguiente ejemplo es un cambio de función no genérico para el intercambio de dos valores 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)")

La salida por encima de la ejecución del programa es:

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

Funciones genéricas pueden acceder a cualquier tipo, tales como int o de cadena.

El siguiente ejemplo es una función genérica para canje de dos valores enteros y de cadena:

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)")

La salida por encima de la ejecución del programa es:

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

versión genérica de esta función utilizando el nombre del tipo de marcador de posición (por lo general representado por la letra T en este caso) en lugar de los nombres de los tipos reales (como Int, o de cadena doble). Marcador de posición nombre de tipo no debe sugerir qué tipo T, pero sugiere a y b deben ser del mismo tipo T, independientemente de qué tipo T representa. Sólo cambio (_: _ :) función cuando pasa en cada tipo de llamada con el fin de determinar el tipo real T representa.

Otra diferencia es que este último nombre de la función seguido por el nombre genérico del tipo de marcador de posición (T) está encerrado entre paréntesis angulares ( ). Los corchetes angulares se les dice que el intercambio Swift T (_: _ :) tipo de una definición de función. Como T es un tipo de marcador de posición con nombre, Swift no es encontrar el nombre de la T. tipo real


tipo genérico

Swift le permite definir sus propios tipos genéricos.

clases personalizadas, estructuras y enumeraciones aplicarse a cualquier tipo que el de la matriz y el uso de diccionario.

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()

La salida por encima de la ejecución del programa es:

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

tipo genérico extendida

Al ampliar un tipo genérico de tiempo (extensión usando palabras clave), que no es necesario proporcionar una lista de parámetros de tipo en la definición extendida. Más conveniente es que la primitiva definición de tipo de parámetro de tipo declarado en la lista se puede ampliar en uso y los nombres de los parámetros del modelo original se utilizará como una referencia a la definición original del parámetro de tipo.

Ejemplos

En el siguiente ejemplo se extiende el tipo TOS genérico, para agregar una propiedad de sólo lectura denominado primer cálculo, devolverá la parte superior actual de los elementos de la pila y no será retirado de la 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)")
}

La salida por encima de la ejecución del programa es:

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

tipo de restricción

Tipo de restricción que especifica un parámetro de tipo debe heredar de la clase especificada o seguir un protocolo o composición específica.

sintaxis de restricción de tipo

Se puede escribir una restricción de tipo en la parte trasera de un tipo de nombres de parámetros, dividido por dos puntos, como parte de la cadena de parámetro de tipo. Tales actúa sobre la base del tipo de sintaxis restricción para las funciones genéricos son como sigue (el mismo tipo genérico de sintaxis):

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

Ejemplos

// 函数可以作用于查找一字符串数组中的某个字符串
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)")
}

La salida por encima de la ejecución del programa es:

llama 的下标索引值为 2

Ejemplos del tipo de asociación

typealias Swift palabra clave utilizada para establecer el tipo de asociación.

Definir un protocolo, a veces declarar uno o más tipo asociado de protocolo de la parte de la definición es muy útil ya.

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)

La salida por encima de la ejecución del programa es:

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

donde las declaraciones

El tipo de limitación para garantizar el cumplimiento de la definición del tipo de función genérica restricción o clase.

Restricciones donde se pueden definir los parámetros de la declaración en la lista de parámetros.

Donde se puede escribir una declaración, seguida de la lista de parámetros de tipo en la parte trasera, donde el estado es seguido por uno o más tipos de restricciones para la asociación, y (o) el equivalente de uno o más tipos y tipos de asociación entre la relación (la igualdad).

Ejemplos

El ejemplo siguiente define una función genérica llamada allItemsMatch, que se utiliza para comprobar si dos instancias de recipiente contiene los mismos elementos en el mismo orden.

Si todos los elementos pueden igualar, y luego volver a un valor booleano true, de lo contrario es falso.

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)

La salida por encima de la ejecución del programa es:

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