Swift 泛型⑫

2020-08-06  本文已影响0人  Aliv丶Zz


泛型可以将类型参数化,提高代码复用率,减少代码量。
注意:

C++ 是通过实现多个不同类型的方法来实现泛型
Swift 是通过传入泛型的元类型来实现泛型

  1. 交换两个Int类型的值
func swapValues(_ v1: inout Int, _ v2: inout Int)  {
    let temp = v1
    v1 = v2
    v2 = temp
}

var n1 = 10
var n2 = 20
swapValues(&n1, &n2)
print(n1, n2) // 20 10
  1. 交换两个入参的值(可能是Int,Double,String),这个时候就要用到泛型
func swapValues2<T>(_ v1: inout T, _ v2: inout T)  {
    (v1,v2) = (v2,v1)
}

var a = 10
var b = 20
swapValues2(&a, &b)
print(a, b)//20 10

a = "ABC"
b = "abc"
swapValues2(&a, &b)
print(a, b)//abc ABC

对于C++来说,会分别生成
func swapValues2(_ v1: inout Int, _ v2: inout Int)
以及 func swapValues2(_ v1: inout String, _ v2: inout String) 两个函数

对于Swift来说,
在传入参数时,会把该参数的元类型(type metadata)一起传入

  1. 泛型函数赋值给变量
func test<T1, T2>(_ v1: T1, _ v2 : T2) -> [Any] {
    return [v1,v2]
}
var fn : (Int, Double) ->([Any]) = test

print(fn(10,20.0))
  1. 泛型类
class Stack<T> {
    var elements = [T]()
    func push(element: T)  {
        elements.append(element)
    }
    func pop()  {
        elements.removeLast()
    }
    func top() -> T {
       elements.last!
    }
}

var stac = Stack<Int>()
stac.push(element: 5)
stac.push(element: 6)
stac.pop()
print(stac.elements)
print(stac.top())
/*
[5, 6]
6
*/
class subStack<T>: Stack<T> {
    
}
  1. 关联类型(协议中实现泛型)
protocol Stackable {
    associatedtype Element// 关联类型
    mutating func push(_ element: Element)
    mutating func pop() -> Element
    func top()  -> Element
    func size() -> Int
}

class StringStack: Stackable {
    typealias Element  = String//给关联类型设定真实类型 可省略

    var elements = [String]()

    func push(_ element: String) {
        elements.append(element)
    }
    func pop() -> String {
        elements.removeLast()
    }
    func top() -> String {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}
class IntStack<E> :Stackable{
    typealias E  =  Int //给关联类型设定真实类型 可省略
    var elements = [Int]()
        
    func push(_ element: Int) {
        elements.append(element)
    }
    func pop() -> Int {
        elements.removeLast()
    }
    func top() -> Int {
        elements.last!
    }
    func size() -> Int {
        elements.count
    }
}
  1. 类型约束
protocol Runnable{
}

func lxys(){
    
    class Person{}
    func swapValues<T: Person&Runnable>(_ a: inout T, _ b: inout T ){
        (a, b) = (b,a)
    }
}

【泛型使用注意点】
示例1: 协议中有associatedtype

image.png
解决方案1:强制转换时可能会出错。
protocol Runnable {
    associatedtype Speed
    var speed : Speed{get}
}

class Person: Runnable {
    var speed: Double {
        10.0
    }
    
}

class Car: Runnable {
    var speed: Int {
        20
    }
}

//func get(_ type: Int) -> Runnable {
//    if type == 0 {
//        return Person()
//    }
//    return Car()
//}
func get<T: Runnable>(_ type: Int) -> T {
    if type == 0 {
        return Person() as! T
    }
    return Car() as! T
}

解决方案2: 不透明类型 some

// 解决方案2
func get(index: Int) -> some Runnable {

    return Car()
}
class Person{
    var per: some Runable{
        return Dog()
    }
}
上一篇下一篇

猜你喜欢

热点阅读