泛型

241 阅读3分钟
  1. 泛型视图解决存储不同的数据类型,或者方法的入参是不同的数据类型。这样可以优雅的减少了很多不必要的重复代码。
func exchangeTwoValue<T>(a:inout T, b: inout T){
    let temp = a
    a = b
    b = temp
}

var a = 3
var b = 4
exchangeTwoValue(a: &a, b: &b)
print(String(a) + " " + String(b))


var c = "abc"
var d = "123"
exchangeTwoValue(a: &c, b: &d)
print(String(c) + " " + String(d))

//系统库函数解决交互两个值
swap(&c, &d)
print(String(c) + " " + String(d))
  1. 利用泛型实现一个自定义栈
//1. 利用泛型实现自定义栈
struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ a: Element){
        items.append(a)
    }
    mutating func pop(){
        items.removeLast()
    }
}

var aStack = Stack<Any>()
aStack.push(1)
aStack.push(2.0)
aStack.push("1")
print(aStack.items)

aStack.pop()
print(aStack.items)
  1. 对泛型类型扩展
//2. 利用扩展返回栈顶
extension Stack {
    var topStack: Element? {
        return items.isEmpty ? nil : items.last
    }
}

print(aStack.topStack as Any)
  1. 类型约束
func findIndex<T: Equatable>(findValue: T, array: [T]) -> Int?{
    for (index, value) in array.enumerated(){
        if value == findValue {
            return index
        }
    }
    return nil
}

var a = [1,2,3,4,5]
print(findIndex(findValue: 3, array: a) as Any)
  1. 关联类型
protocol Container {
    associatedtype Item
    mutating func append(item: Item)
    var count: Int{get}
    subscript(index: Int) -> Item { get }
}

struct Stack<Element>: Container {
    var items = [Element]()
    mutating func push(_ a: Element){
        items.append(a)
    }
    mutating func pop(){
        items.removeLast()
    }
    
    mutating func append(item: Element) {
        push(item)
    }
    
    var count: Int{
        return items.count
    }
    
    subscript(index: Int) -> Element {
       return items[index]
    }
}

var aStack = Stack<Any>()
aStack.push(1)
aStack.push(2.0)
aStack.push("1")
print(aStack.items)

print(aStack[2])
  1. 协议里的关联类型可以添加条件
protocol Container {
    associatedtype Item: Equatable
    mutating func append(item: Item)
    var count: Int{get}
    subscript(index: Int) -> Item { get }
}
  1. 泛型Where语句
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int {get}
    subscript(item: Int) -> Item{get}
}

struct Stack<Element>: Container {
    var items = [Element]()
    mutating func append(_ item: Element) {
        items.append(item)
    }

    var count: Int {
        return items.count
    }

    subscript(item: Int) -> Item {
        return items[item]
    }
}

extension Array: Container {}

func allItemsMatch<T: Container, U: Container> (a: T, b: U) -> Bool

    where T.Item == U.Item,  T.Item: Equatable  {
        if a.count != b.count {
            return false
        }

        for index in 0..<a.count {
            if a[index] != b[index] {
                return false
            }
        }

        return true
}

var a = Stack<String>()
a.append("a")
a.append("b")
a.append("c")
a.append("d")
a.append("e")
a.append("f")

var b = [
        "a",
        "1",
        "c",
        "d",
        "e",
        "f"
]

print(allItemsMatch(a: a, b: b))
  1. 扩展泛型协议使用where语句
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int {get}
    subscript(item: Int) -> Item{get}
}

struct Stack<Element>: Container {
    var items = [Element]()
    mutating func append(_ item: Element) {
        items.append(item)
    }

    var count: Int {
        return items.count
    }

    subscript(item: Int) -> Item {
        return items[item]
    }
}

extension Array: Container {}

func allItemsMatch<T: Container, U: Container> (a: T, b: U) -> Bool

    where T.Item == U.Item,  T.Item: Equatable  {
        if a.count != b.count {
            return false
        }

        for index in 0..<a.count {
            if a[index] != b[index] {
                return false
            }
        }

        return true
}

extension Stack where Element: Equatable {
    //1. 扩展判断是否是栈顶
    func isTopStack(item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        
        return topItem == item
    }
    
    //2. 扩展判断栈低
    func isBottomStack(item: Element) -> Bool {
        return count >= 1 && items[0] == item
    }
}

var aStack = Stack<String>()
aStack.append("a")
aStack.append("b")
aStack.append("c")

print(aStack.isTopStack(item: "c"))
print(aStack.isBottomStack(item: "b"))

//扩展Container协议,新增如果每个元素都是小数类型,那么可以计算平均值
extension Container where Item == Double {
    func avg() -> Double {
        var sum = 0.0
        for item in 0..<count{
            sum += self[item]
        }
        return sum/Double(count)
    }
}

var b = [
        1.0,
        2.0,
        3.0,
        4.0
]

print(b.avg())
  1. 泛型下标
// 1. 封装数据结构
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int{get}
    subscript(index: Int) -> Item{get}
}

extension Array: Container {}

struct Stack<Element>: Container {
    var items = [Element]()
    mutating func append(_ item: Element) {
        items.append(item)
    }
    
    var count: Int {
        return items.count
    }
    
    subscript(index: Int) -> Element {
        return items[index]
    }
}

// 2. 给两种数据结构扩展一个方法
extension Container {
    subscript<T: Sequence>(set: T) -> [Item]
        where T.Iterator.Element == Int {
            var items = [Item]()
            for item in set{
                items.append(self[item])
            }
            return items
    }
}

var aStack = Stack<String>()
aStack.append("a")
aStack.append("b")
aStack.append("c")
aStack.append("d")

print(aStack[[0,2,3]])

//打印如下
//["a", "c", "d"]
  1. 总结
    1. 泛型视图解决存储多种数据类型,和方法的入参是多种数据类型。
    2. 一个方法入参不用泛型切其实可以用Any来解决。
    3. 利用Any来代替泛型不好,我们应该在方法入参用泛型。
      1. 泛型可以做到入参和返回值得统一性。但是Any做不多。
      2. 泛型可以在调用时候指定特定的数据类型。但是Any也做不到。 泛型