Swift泛型
时间:2020-02-23 14:44:01 来源:igfitidea点击:
在本教程中,我们将讨论Swift中的泛型。
我们将看到如何扩展泛型类型,对泛型使用类型约束。
Swift泛型(Swift Generics)
泛型用于编写可在多种类型之间工作的灵活且可重用的代码。
因此,我们可以为普通类型设置通用类型,而不是为每种类型(如Int,String等)创建不同的函数/结构。
通用类型也称为占位符类型。
通常,当我们在函数中传递类型化参数时,我们会执行以下操作:
func printMe(a: Int) { print(a) } printMe(a: 1) func printMe(a: String) { print(a) } printMe(a: "Anupam")
现在,我们可以轻松地使用通用参数,而不是为每种类型创建不同的函数。
为了创建一个通用函数,您需要在尖括号中的函数名称之后设置一个占位符值:<Element>。
您需要使用与参数/返回类型相同的占位符值。
您也可以传递多个占位符值。
通常,如果通用参数占位符不代表任何内容,请使用T,U,V等。
func printMe<T>(a: T) { print(a) } printMe(a: 1) printMe(a: "Anupam")
另一个示例:交换值的经典方式:
func swapAandB<T>(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA } var x = "hello" var y = "world" swapAandB(&x, &y) print(x) print(y) var x1 = 2 var y1 = 3 swapAandB(&x1, &y1) print(x1) print(y1)
您只能在所有T中传递相同的类型。
设置不同的类型将导致编译器错误。
我们可以通过使用两个通用参数来解决上述规则。
我们必须在函数标头本身中声明它们两者:
func printTandU<T,U>(a:T,b:U) { print("T is \(a) and U is \(b)") } printTandU(a: 1, b: "Swift Generics")
通用类型约束
我们也可以约束泛型类型以使其符合某种类型。
class Person{ var name:String? var age:Int init(name:String, age:Int) { self.name = name self.age = age } } func printDetails<T: Person>(a: T, b: T) { print("a is \(a.name ?? "NA") and age \(a.age)") print("b is \(b.name ?? "NA") and age \(b.age)") } var p1 = Person(name: "Harry Potter",age: 11) var p2 = Person(name: "Dumbledore",age: 700) printDetails(a: p1, b: p2)
T符合类型Person。
因此,您不能在上述代码中传递任何不是Person类型的值。
执行以下操作会导致崩溃。
class A{ } printDetails(a: A(), b: A()) //Class A isn't of the type Person.
子类将符合通用参数类型。
泛型类型必须符合协议的另一个示例:
func compareAandB<T: Equatable>(a: T, b: T) { print("a == b ? \(a==b)") } compareAandB(a: 2, b: 3) compareAandB(a: "Hi", b: "Hi")
如果没有Equatable协议," =="将无法正常工作。
在泛型类型上使用扩展
我们可以通过以下方式对泛型类型使用扩展:
struct Stack<T> { var items = [T]() mutating func push(_ item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } } var stackOfInt = Stack<Int>() stackOfInt.push(2) stackOfInt.push(3) extension Stack { var top: T? { return items.isEmpty ? nil : items[items.count - 1] } }
我们不必再次在扩展名中设置通用类型。
使用where子句
我们可以使用where子句进行更严格的泛型类型约束检查。
在where子句中,我们可以添加其他条件。
protocol Hogwarts{} protocol Muggles{} class Person : Hogwarts{ var name:String? var age:Int init(name:String, age:Int) { self.name = name self.age = age } } class M: Person, Muggles{} func printDetails<T:Person>(a: T) where T:Muggles { print("a is \(a.name ?? "NA") and age \(a.age)") } var p1 = Person(name: "Harry Potter",age: 11) var m2 = M(name: "Hermione",age: 700) var p3 = Person(name: "Ron",age: 11) printDetails(a: m2) //printDetails(a: p1)
因此,在上面的代码中,我们添加了一个检查器,其中类型T除了符合类Person之外,还必须符合Muggles协议。
因此,在上面的代码中只需要使用M类的类型。而不是Person类。