23.泛型

作者: LucXion | 来源:发表于2021-07-26 09:10 被阅读0次

泛型代码让你能根据自定义的需求,编写出适用于任意类型的、灵活可复用的函数及类型。你可避免编写重复的代码,而是用一种清晰抽象的方式来表达代码的意图。

函数、类型参数

func swapTwo_Int(_ a:inout Int,_ b: inout Int){
    let temp = a
    a = b
    b = temp
}
func swapTwo_String(_ a:inout String,_ b: inout String){
    let temp = a
    a = b
    b = temp
}
// <T>占位符类型
func swapTwo<T>( _ a:inout T, _ b:inout T){
    let temp = a
    a = b
    b = temp
}

命名规范:大多情况下,类型参数具有描述下的名称,例如字典 Dictionary<Key, Value> 中的 KeyValue 及数组 Array<Element> 中的 Element,这能告诉阅读代码的人这些参数类型与泛型类型或函数之间的关系。然而,当它们之间没有有意义的关系时,通常使用单个字符来表示,例如 TUV

类型 + 扩展 + 类型约束

除了泛型函数,Swift 还允许自定义泛型类型。这些自定义类、结构体和枚举可以适用于任意类型,类似于 ArrayDictionary

  1. 类型 + 泛型

    struct Stack<Element>{ // <Element>占位符类型
        var stack : [Element] = []
        mutating func push(addIn element:Element) {
            stack.append(element)
        }
        mutating func pop() {
            stack.removeLast()
        }
    }
    
  2. 延展 + 泛型

    extension Stack {
        var topItem:Element? { // 可以直接使用类定义处的泛型
            return stack.isEmpty ? nil: stack.last
        }
    }
    var stackInt = Stack<Int>()// 定义泛型类型
    stackInt.push(addIn: 111)
    stackInt.push(addIn: 9999)
    stackInt.pop()
    print(stackInt.topItem!)
    
  3. 类 + 泛型 + 类型约束

    struct CompareInt {
        static func compare(num1:Int,num2:Int) -> Bool {
            return num1 == num2
        }
    }
    struct CompareType<T:Equatable> {
        static func compare(num1:T,num2:T) -> Bool {
            return num1 == num2
        }
    }
    print(CompareType.compare(num1: 1, num2: 1))
    

关联类型

关联类型通过 associatedtype 关键字来指定

  1. 协议 + 关联类型

    protocol stack {
        associatedtype Item // associatedtype 关键字来声明关联类型
        var list:[Item]{set get}
        func push(item:Item)
        func pop()
    }
    class Person:stack { 
        typealias Item = Int  // typealias 来指定关联类型,也可以省略,省略以后Swift会在第一次指定关联类型的地方确定所有关联类型
        var list : [Item] = []
        func push(item: Int) {
            list.append(item)
        }
        func pop() {
            list.removeLast()
        }
    }
    
  2. 扩展 + 关联类型

    • 无法直接在扩展中实现,只有在类定义的时候有同名的实现,才能在扩展中声明该类遵循了该协议
  3. 给关联类型添加约束

    protocol Container {
        associatedtype Item: Equatable
    }
    
  4. 关联类型约束里使用协议

    protocol P1 {
        associatedtype Item
        func push(item:Item)
    }
    protocol P2:P1 {
        /*
         Suffix 必须遵循协议 P2
         并且 它的 Item 类型必须是和容器里的 Item 类型相同
         */
        associatedtype Suffix:P2 where Suffix.Item == Item
        func response() -> Suffix
    }
    class Person:P2 {
        var list:[Int] = []
        func push(item: Int) {
            list.append(item)
        }
        func response() -> Person { // Person中的Item = Int , 此处 Item = Int
            return self
        }
    }
    

泛型 where 语句

对关联类型添加约束通常是非常有用的。你可以通过定义一个泛型 where 子句来实现。通过泛型 where 子句让关联类型遵从某个特定的协议,以及某个特定的类型参数和关联类型必须类型相同。

protocol Container {
    associatedtype Item // Equatable 不能写在这里,否则 Array中找不到同名实现
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

struct Stack:Container {
    
    var list:[Item] = []
//    Container 实现
    typealias Item = Int
    var count: Int {
        return list.count
    }
    mutating func append(_ item: Item) {
        list.append(item)
    }
    subscript(i: Int) -> Item {
        return list[i]
    }
}

extension Array:Container {} // 已经有了实现,可以在延展中声明遵循了协议

/// where 关键字写在 返回值后,多个条件用逗号隔开
func allItemsMatch<C1:Container,C2:Container>(parameter1:C1,parameter2:C2)->Bool where C1.Item == C2.Item,C1.Item:Equatable {
    
    if parameter1.count != parameter2.count {
        return false
    }
    for index in 0..<parameter1.count {
        if parameter1[index] != parameter2[index] {
            return false
        }
    }
    return true
}

var c1 = Stack.init(list: [1,2,3,4,6])
var c2 = [1,2,3,4,5]
print(allItemsMatch(parameter1: c1, parameter2: c2))

具有泛型 where子句的 扩展

extension Stack where Element: Equatable { // 在延展后给泛型添加约束,只有满足条件才能调用延展中的方法
    func isTop(_ item: Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        return topItem == item
    }
}

包含上下文关系的 where 分句

extension Container {
    func average() -> Double where Item == Int { // 给某个指定函数添加泛型约束,只有满足条件才能使用这个方法
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }
    func endsWith(_ item: Item) -> Bool where Item: Equatable {
        return count >= 1 && self[count-1] == item
    }
}

泛型下标

extension Container {
    subscript<Indices: Sequence>(indices: Indices) -> [Item]
        where Indices.Iterator.Element == Int { // 定义泛型 + where 约束条件
            var result: [Item] = []
            for index in indices {
                result.append(self[index])
            }
            return result
    }
}

相关文章

  • 23.泛型

    泛型代码让你能根据自定义的需求,编写出适用于任意类型的、灵活可复用的函数及类型。你可避免编写重复的代码,而是用一种...

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

  • 【泛型】通配符与嵌套

    上一篇 【泛型】泛型的作用与定义 1 泛型分类 泛型可以分成泛型类、泛型方法和泛型接口 1.1 泛型类 一个泛型类...

  • 泛型的使用

    泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法 泛型类 泛型接口 泛型通配符 泛型方法 静态方法与...

  • Java 泛型

    泛型类 例如 泛型接口 例如 泛型通配符 泛型方法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型上下边...

  • 探秘 Java 中的泛型(Generic)

    本文包括:JDK5之前集合对象使用问题泛型的出现泛型应用泛型典型应用自定义泛型——泛型方法自定义泛型——泛型类泛型...

  • Web笔记-基础加强

    泛型高级应用 自定义泛型方法 自定义泛型类 泛型通配符? 泛型的上下限 泛型的定义者和泛型的使用者 泛型的定义者:...

  • 重走安卓进阶路——泛型

    ps.原来的标题 为什么我们需要泛型? 泛型类、泛型接口和泛型方法(泛型类和泛型接口的定义与泛型方法辨析); 如何...

  • Kotlin泛型的高级特性(六)

    泛型的高级特性1、泛型实化2、泛型协变3、泛型逆变 泛型实化 在Java中(JDK1.5之后),泛型功能是通过泛型...

  • Java 19-5.1泛型

    泛型类定义泛型类可以规定传入对象 泛型类 和泛型方法 泛型接口 如果实现类也无法确定泛型 可以在继承类中确定泛型:

网友评论

      本文标题:23.泛型

      本文链接:https://www.haomeiwen.com/subject/fldpmltx.html