สวิฟท์ 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) ถูกปิดล้อมอยู่ในวงเล็บมุม (
ประเภททั่วไป
สวิฟท์ช่วยให้คุณกำหนดประเภททั่วไปของคุณเอง
ชั้นเรียนที่กำหนดเองโครงสร้างและ 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 语句"]