Latest web development tutorials

สวิฟท์ Generics

สวิฟท์ให้ทั่วไปมีความยืดหยุ่นและช่วยให้คุณเขียนฟังก์ชั่นนำมาใช้ใหม่และประเภท

ห้องสมุดมาตรฐานสวิฟท์ที่ถูกสร้างขึ้นโดยทั่วไปรหัส

อาร์เรย์สวิฟท์และพจนานุกรมประเภทชุดทั่วไป

คุณสามารถสร้างอาร์เรย์ Int คุณสามารถสร้างอาร์เรย์สตริงหรือแม้แต่อาร์เรย์ข้อมูลได้ประเภทอื่น ๆ ของสวิฟท์ใด ๆ

ตัวอย่างต่อไปนี้คือการแลกเปลี่ยนไม่ใช่หน้าที่ทั่วไปสำหรับการแลกเปลี่ยนของสองค่า 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)")

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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

ฟังก์ชั่นทั่วไปสามารถเข้าถึงชนิดใด ๆ เช่น Int หรือสตริง

ตัวอย่างต่อไปนี้เป็นฟังก์ชั่นทั่วไปสำหรับการแลกเปลี่ยนแลกเปลี่ยนสอง Int และค่า 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)")

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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

รุ่นทั่วไปของฟังก์ชั่นนี้โดยใช้ชื่อประเภทตัวยึด (มักจะแทนด้วยตัวอักษร T ในกรณีนี้) แทนชื่อประเภทที่เกิดขึ้นจริง (เช่น Int, สตริงหรือเตียงคู่) ชื่อประเภทตัวยึดไม่ต้องแนะนำสิ่งที่ประเภท T แต่มันแสดงให้เห็น A และ B จะต้องเป็นชนิดเดียวกัน T โดยไม่คำนึงถึงสิ่งที่ประเภท T หมายถึง แลกเปลี่ยนเท่านั้น (_: _ :) ฟังก์ชั่นเมื่อผ่านในแต่ละประเภทการโทรเพื่อกำหนดประเภท T หมายถึงที่เกิดขึ้นจริง

แตกต่างก็คือว่าชื่อฟังก์ชั่นนี้หลังตามด้วยชื่อสามัญประเภทตัวยึด (T) ถูกปิดล้อมอยู่ในวงเล็บมุม ( ) วงเล็บมุมบอกว่าสวิฟท์ T คือการแลกเปลี่ยน (_: _ :) ฟังก์ชั่นประเภทที่กำหนดไว้ ตั้งแต่ T เป็นตัวยึดชื่อชนิดสวิฟท์ไม่ได้ที่จะหาชื่อของ T. ประเภทที่เกิดขึ้นจริง


ประเภททั่วไป

สวิฟท์ช่วยให้คุณกำหนดประเภททั่วไปของคุณเอง

ชั้นเรียนที่กำหนดเองโครงสร้างและ enumerations นำไปใช้กับประเภทใด ๆ เป็นแถวและการใช้พจนานุกรม

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

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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

การขยายประเภททั่วไป

เมื่อคุณขยายประเภททั่วไปของเวลา (ส่วนขยายโดยใช้คำหลัก) คุณไม่จำเป็นต้องให้รายการประเภทพารามิเตอร์ในการขยายความหมาย ความสะดวกสบายมากขึ้นก็คือว่าคำนิยามประเภทพารามิเตอร์ชนิดดั้งเดิมประกาศในรายการสามารถขยายได้ในการใช้งานและชื่อพารามิเตอร์จากชนิดเดิมจะถูกนำมาใช้เป็นข้อมูลอ้างอิงถึงคำนิยามเดิมของพารามิเตอร์ชนิด

ตัวอย่าง

ตัวอย่างต่อไปนี้ขยายประเภท TOS ทั่วไปเพื่อเพิ่มอ่านอย่างเดียวชื่อคุณสมบัติคำนวณแรกก็จะกลับมาอยู่อันดับปัจจุบันขององค์ประกอบสแต็คและจะไม่ถูกลบออกจากสแต็ค

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

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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

ประเภท จำกัด

ประเภท จำกัด ระบุว่าพารามิเตอร์ชนิดต้องสืบทอดจากคลาสที่ระบุหรือตามโปรโตคอลที่เฉพาะเจาะจงหรือองค์ประกอบ

ไวยากรณ์ จำกัด ประเภท

คุณสามารถเขียนเป็นข้อ จำกัด ประเภทในด้านหลังของชื่อพารามิเตอร์ชนิดแบ่งตามลำไส้ใหญ่ซึ่งเป็นส่วนหนึ่งของห่วงโซ่พารามิเตอร์ชนิด การกระทำดังกล่าวบนพื้นฐานของประเภทของไวยากรณ์ข้อ จำกัด สำหรับการทำงานทั่วไปมีดังนี้ (ประเภททั่วไปเดียวกันของไวยากรณ์):

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

ตัวอย่าง

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

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

llama 的下标索引值为 2

ตัวอย่างของประเภทของสมาคม

typealias สวิฟท์หลักที่ใช้ในการกำหนดประเภทของสมาคม

กำหนดโปรโตคอลบางครั้งประกาศหนึ่งหรือมากกว่าหนึ่งประเภทที่เกี่ยวข้องของโปรโตคอลส่วนหนึ่งของความหมายจะเป็นประโยชน์เป็นอย่างมาก

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)

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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

ที่งบ

ประเภทของข้อ จำกัด เพื่อให้สอดคล้องกับความหมายของประเภทของฟังก์ชั่นทั่วไปข้อ จำกัด หรือการเรียน

คุณสามารถกำหนดค่าพารามิเตอร์ของคำสั่งที่ จำกัด ในรายการพารามิเตอร์

ที่คุณสามารถเขียนคำสั่งตามด้วยรายการพารามิเตอร์ชนิดในด้านหลังที่คำสั่งจะตามด้วยหนึ่งหรือมากกว่าหนึ่งประเภทของข้อ จำกัด สำหรับการเชื่อมโยงและ (หรือ) เทียบเท่าของหนึ่งหรือหลายชนิดและประเภทความสัมพันธ์ระหว่าง (ความเสมอภาค) ความสัมพันธ์

ตัวอย่าง

ตัวอย่างต่อไปนี้กำหนดฟังก์ชันทั่วไปชื่อ allItemsMatch ที่ใช้ในการตรวจสอบว่าทั้งสองกรณีของตู้คอนเทนเนอร์ที่มีองค์ประกอบเดียวกันในลำดับเดียวกัน

ถ้าองค์ประกอบทั้งหมดที่สามารถจับคู่แล้วกลับไปที่ค่าบูลีนของจริงมิฉะนั้นมันเป็นเท็จ

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)

เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:

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