Latest web development tutorials

Swift Generics

Swift fornece uma forma flexível genérica e permite que você escreva funções reutilizáveis ​​e tipos.

biblioteca padrão Swift é construído por código genérico.

matrizes Swift e tipos de dicionários são conjunto genérico.

Você pode criar uma matriz Int, você pode criar uma matriz String, ou mesmo conjunto de dados pode ser qualquer tipo de outra Swift.

O exemplo a seguir é uma troca de função não-genérico para a troca de dois 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)")

A saída de execução de programa acima é:

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

funções genéricas pode acessar qualquer tipo, tais como Int ou cadeia.

O exemplo a seguir é uma função genérica para a troca de swap dois valores int e string:

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

A saída de execução de programa acima é:

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

versão genérica de esta função usando o nome do tipo de espaço reservado (normalmente representado pela letra T, neste caso), em vez dos nomes de tipos reais (como Int, String ou duplo). Nome do tipo de espaço reservado não deve sugerir que tipo T, mas sugere a e b devem ter o mesmo tipo T, independentemente do tipo T representa. Apenas câmbio (_: _ :) função quando passou em cada tipo de chamada a fim de determinar o tipo real T representa.

Outra diferença é que este nome da função última seguido pelo nome genérico do tipo de espaço reservado (T) está entre parênteses em ângulo ( ). Os suportes angulares dito Swift que T é a troca (_: _ :) uma função do tipo definido. Como T é um tipo de espaço reservado com o nome, Swift não é encontrar o nome do actual tipo T.


tipo genérico

Swift permite definir seus próprios tipos de genéricos.

classes personalizadas, estruturas e enumerações aplicado a qualquer tipo de matriz e uso de dicionário.

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

A saída de execução de programa acima é:

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

tipo genérico estendida

Quando você estende um tipo genérico de tempo (extensão usando palavras-chave), você não precisa fornecer uma lista de parâmetro de tipo na definição estendida. Mais conveniente é que a definição de tipo tipo de parâmetro primitiva declarou na lista pode ser expandida em uso e os nomes dos parâmetros do tipo original será usado como uma referência para a definição original do parâmetro de tipo.

Exemplos

O exemplo a seguir estende o tipo TOS genérica, para adicionar uma propriedade somente leitura chamada primeiro cálculo, ele irá retornar ao topo atual dos elementos da pilha e não será removido da pilha.

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

A saída de execução de programa acima é:

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

tipo de restrição

Tipo de restrição especifica que um parâmetro do tipo deve herdar da classe especificada ou seguir um protocolo ou composição específica.

sintaxe de restrição de tipo

Você pode escrever uma restrição de tipo na parte de trás de um nomes de parâmetro de tipo, dividido por dois pontos, como parte da cadeia tipo de parâmetro. Tais actua sobre a base do tipo de sintaxe de restrição para as funções genéricas são os seguintes (o mesmo tipo genérico de sintaxe):

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

Exemplos

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

A saída de execução de programa acima é:

llama 的下标索引值为 2

Exemplos do tipo de associação

typealias Swift palavra-chave usada para definir o tipo de associação.

Definir um protocolo, às vezes declarar uma ou tipo mais associado da parte do protocolo da definição é muito útil como.

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)

A saída de execução de programa acima é:

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

Sempre que as declarações

O tipo de restrição para assegurar a conformidade com a definição do tipo de função genérica restrição ou classe.

Você pode definir os parâmetros da declaração em que a restrição na lista de parâmetros.

Onde você pode escrever uma declaração, seguida pela lista de parâmetro de tipo na parte de trás, onde a declaração é seguida por um ou mais tipos de restrições para a associação, e (ou) o equivalente a um ou mais tipos e tipos de associação entre relacionamento (igualdade).

Exemplos

O exemplo a seguir define uma função genérica chamado allItemsMatch, utilizado para verificar se duas instâncias do recipiente contém os mesmos elementos na mesma ordem.

Se todos os elementos pode corresponder, em seguida, retornar para um valor booleano de true, caso contrário, ela é 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)

A saída de execução de programa acima é:

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