Generik Swift


Swift menyediakan generik yang membolehkan anda menulis fungsi dan jenis yang fleksibel dan boleh digunakan semula.

Pustaka standard Swift dibina dengan kod generik.

Jenis tatasusunan dan kamus Swift ialah kedua-dua set generik.

Anda boleh mencipta tatasusunan Int, tatasusunan Rentetan atau mana-mana tatasusunan data jenis Swift yang lain.

Contoh berikut ialah pertukaran fungsi bukan generik yang digunakan untuk menukar dua nilai 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)")

Hasil keluaran pelaksanaan program di atas ialah:

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

Generik fungsi boleh mengakses mana-mana Jenis, seperti Int atau String.

Contoh berikut ialah pertukaran fungsi generik yang digunakan untuk menukar dua nilai Int dan 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)")

Hasil keluaran pelaksanaan program di atas ialah:

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

The jenis generik fungsi ini Versi menggunakan nama jenis pemegang tempat (biasanya diwakili oleh huruf T dalam kes ini) dan bukannya nama jenis sebenar (seperti Int, String atau Double). Nama jenis pemegang tempat tidak menunjukkan jenis T mesti, tetapi ia menunjukkan bahawa a dan b mestilah jenis T yang sama, tanpa mengira jenis T yang mewakili. Hanya jenis sebenar yang diluluskan setiap kali fungsi exchange(_:_:) dipanggil boleh menentukan jenis T mewakili.

Satu lagi perbezaan ialah nama jenis pemegang tempat (T) mengikut nama fungsi generik disertakan dalam kurungan sudut (


Jenis generik

Swift membolehkan anda menentukan jenis generik anda sendiri.

Kelas, struktur dan penghitungan tersuai berfungsi dengan mana-mana jenis, sama seperti penggunaan Array dan Kamus

Program di atas ialah:

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


Jenis generik lanjutan

Apabila anda melanjutkan jenis generik (menggunakan kata kunci sambungan), anda tidak perlu memasukkannya dalam definisi sambungan Menyediakan senarai parameter jenis Malah lebih mudah, senarai parameter jenis diisytiharkan dalam definisi jenis asal tersedia dalam sambungan, dan nama parameter daripada jenis asal digunakan sebagai rujukan kepada parameter jenis dalam definisi asal >

Contoh

Contoh berikut melanjutkan jenis TOS generik dan menambah. sifat pengiraan baca sahaja yang dinamakan dahulu, yang akan mengembalikan elemen di bahagian atas tindanan semasa tanpa mengalihkannya daripada tindanan Kecuali

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

Hasil keluaran program di atas. pelaksanaan ialah:

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

Kekangan jenis

Kekangan jenis menentukan kelas yang mesti diwarisi daripada kelas yang ditentukan

Sintaks kekangan jenis

<🎜. > Anda boleh menulis kekangan jenis selepas nama parameter jenis, dipisahkan oleh titik bertindih, sebagai jenis Bahagian rantaian parameter Sintaks asas untuk kekangan jenis ini pada fungsi generik adalah seperti berikut (sama seperti sintaks untuk jenis generik. ):

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

Contoh

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

Output pelaksanaan program di atas Hasilnya ialah:

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

Contoh jenis yang berkaitan


Kata kunci typealias digunakan dalam Swift untuk menetapkan jenis yang berkaitan

Apabila mentakrifkan protokol, kadangkala a atau diisytiharkan adalah sangat berguna untuk mempunyai berbilang jenis yang berkaitan sebagai sebahagian daripada definisi protokol daripada pelaksanaan program di atas ialah:

llama 的下标索引值为 2

Di mana kekangan jenis pernyataan

boleh memastikan bahawa jenis mematuhi kekangan yang menentukan bagi fungsi atau kelas generik

.

Anda boleh menentukan kekangan parameter melalui mana pernyataan dalam senarai parameter.

Anda boleh menulis pernyataan where serta-merta mengikuti senarai parameter jenis, diikuti dengan satu atau lebih kekangan pada jenis yang berkaitan dan/atau satu atau lebih kekangan antara jenis dan jenis yang berkaitan.

Contoh

Contoh berikut mentakrifkan fungsi generik bernama allItemsMatch untuk menyemak sama ada dua tika Container mengandungi elemen yang sama dalam susunan yang sama.

Jika semua elemen boleh dipadankan, maka kembalikan nilai Boolean yang benar, jika tidak, ia akan menjadi palsu.

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)

Hasil keluaran pelaksanaan program di atas ialah:

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