1.泛型:
用于编写灵活且可重用的代码,这些代码可以跨多种类型工作。因此,我们可以设置泛型类型,而不是为Int、String等每个类型创建不同的函数/结构。泛型类型也称为占位符类型。
要创建泛型函数,需要在尖括号中的函数名后面设置一个占位符值:
通常,如果泛型参数占位符不表示任何内容,请使用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)
泛型只能是同一类型的,不同类型会报错
我们可以通过使用两个泛型参数来处理上述规则。我们必须在函数头本身中声明它们:
func printTandU<T,U>(a:T,b:U){
print("T is \(a) and U is \(b)")
}
printTandU(a:1,b:"Swift Generics")
2.泛型约束
我们还可以约束泛型类型以符合某个类型。
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类型的值。
子类将符合泛型参数类型。
泛型类型必须符合协议的另一个示例:
func compareAandB<T:Equatable>(a:T,b:T){
print("a == b ? \(a==b)")
}
compareAandB(a:2,b:3)
compareAandB(a:"Hi",b:"Hi")
==将不起作用,当没有Equatable协议时
3.对泛型类型使用扩展
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)
print(stackOfInt.items)//打印结果:[2,3]
var stackOfString = Stack<String>()
stackOfString.push("Hello")
stackOfString.push("World")
print(stackOfString.items)//打印结果:["Hello", "World"]
我们不必再次在扩展中设置泛型类型。
extension Stack{
var top : T?{
return items.isEmpty ? nil : items[items.count - 1]
}
}
4.使用where子句进行泛型类型检查
我们可以使用where子句进行更严格的泛型类型约束检查。在where子句中我们可以添加附加条件。
protocol Hogwarts{}
protocol Muggles {}
class People : Hogwarts{
var name : String?
var age : Int
init(name:String,age:Int){
self.name = name
self.age = age
}
}
class M : People,Muggles{}
func printDetailsTemp<T:People>(a:T) where T:Muggles{
print("a is \(a.name ?? "NA") and age \(a.age)")
}
var person1 = People(name:"Harry Potter",age:11)
var m2 = M(name:"Hermione",age:700)
var person3 = People(name:"Ron",age:11)
printDetailsTemp(a : m2)//打印结果:a is Hermione and age 700
printDetailsTemp(a : person1)//编译错误:global function 'printDetailsTemp(a:)' requires that 'People' conform to 'Muggles'
因此,在上面的代码中,我们添加了一个checker,其中类型T除了符合类People之外,还必须符合Muggles协议。所以,在上面的代码中,它只接受类M的类型。而不是People这个类型