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类。

