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这个类型

posted on 2021-07-21 16:09  蓬松小辉煌  阅读(37)  评论(0编辑  收藏  举报