美文网首页
swift中泛型的使用

swift中泛型的使用

作者: 傲骨天成科技 | 来源:发表于2021-07-16 09:46 被阅读0次

    一、函数中使用泛型

    比如一个打印字符串的方法:

    func myPrintString(str:String){
         print(str)
    }
    

    打印出来就直接是字符串类型的

    如果我们打印的是一个任意类型的呢?我们可以使用Any试试

    // 打印任何东西
    func myPrintAny(arg:Any){
         print(any1)
    }
    

    使用Any是可以的,但是如果我们有多个参数呢,且要求一致呢?

        func myPrintAny(any1:Any, any2:Any){
            print(any1)
            print(any2)
        }
    

    这样的写法是可以使用任意类型了,但是没有限制住两个参数类型是一样的。导致的结果是对调用此API的人要求特别高,不是我们想要的。

    这时泛型就有了用武之地了

        // 打印任何东西
        func myPrint<T>(any1:T, any2:T){
            print(any1)
            print(any2)
        }
    

    从上面的几个事例中可以看出泛型的优势,提升了代码的可复用性、安全性。

    泛型和Any的区别?

    从表面上看两者没有区别。但是,泛型可以用于定义灵活的函数,类型检查仍然由编译器负责。而Any可以逃避开我们swift的类型系统。因此,可以的话尽量不要使用Any。

    二、类中泛型

    实现一个数组中的元素可以是任意类型,但是所有元素又必须是同一类型。

    //类作用域
    class YJKStack<T>: NSObject {
        //栈空间
        private var list:[T] = []
        
        //进栈
        public func push(item:T){
            list.append(item)
        }
        
        //出栈
        public func pop() -> T{
            return list.removeLast()
        }
    }
    

    当我们扩展含有泛型的类的时候,泛型是可以直接在扩展中使用的。

    extension YJKStack{
        /// 获取栈顶元素
        public func getLast() -> T?{
            return list.last
        }
    }
    

    三、泛型类型约束

    1.泛型是某个类的子类
    class YJKProtocolStack<T: CClass >: NSObject {
        //栈空间
        private var list:[T] = []
        
        //进栈
        public func push(item:T){
            list.append(item)
        }
        
        //出栈
        public func pop() -> T{
            return list.removeLast()
        }
    }
    
    class CClass : NSObject {
    }
    
    2.泛型必须要实现某个或几个协议
    //class YJKProtocolStack<T: A&B>  须实现多个协议的话,用 & 符号链接就好啦。
    class YJKProtocolStack<T: A&B>: NSObject {
        //栈空间
        private var list:[T] = []
        
        //进栈
        public func push(item:T){
            list.append(item)
        }
        
        //出栈
        public func pop() -> T{
            return list.removeLast()
        }
    }
    
    protocol A {
        
        func myPrintA(item: Int)
    }
    
    protocol B {
        
        func myPrintB(item: Int)
    }
    
    class ClassAB: NSObject, A, B {
        func myPrintA(item: Int) {
            
            print("我的天神A")
        }
        
        func myPrintB(item: Int) {
            print("我的天神B")
        }
        
        
    }
    
    
    // 使用
    var stack:YJKProtocolStack = YJKProtocolStack<ClassAB>.init()
    

    四、结构体中的泛型使用

    和类里面的泛型使用是一样的

    五、协议中泛型使用需要使用关联类

    //一敲出来,编译器就提示你错误啦,并且告诉你怎么写了。
    protocol C<T> {
    
    }
    
    //正确的写法就是下面这样的哦
    protocol C {
        // Swift 中使用 associatedtype 关键字来设置关联类型实例
        // 具体类型由实现类来决定
        associatedtype ItemType
        
        func itemAtIndex(index:Int) -> ItemType
        
        func myPrint(item:ItemType)
        
        // 局部作用域的泛型和类的写法是一样的。
        func test<T>(a:T)
    }
    
    //协议的泛型约束
    protocol D {
        associatedtype ItemType:A
    }
    

    需要结合使用该协议的类是怎么使用的

    //遵循了 C 协议的类
    class CClassOne<T>:C{
        
        //要指定 C 协议中, ItemType 的具体类型
        typealias ItemType = T
        
        public var list:[ItemType] = []
        
        //协议方法的实现
        func itemAtIndex(index:Int) -> ItemType{
            return list[index]
        }
        
        func myPrint(item:ItemType){
            
        }
        
        func test<T>(a: T) {
            
        }
    }
    
    //实现2
    class CClassTwo:C{
        
        typealias ItemType = Int
        
        public var list:[ItemType] = []
        func itemAtIndex(index:Int) -> ItemType{
            return list[index]
        }
        
        func myPrint(item:ItemType){
            
        }
        
        func test<T>(a: T) {
            
        }
    }
    

    通过上面的例子,看出只要实现类中指定ItemType的类型就好了。这个类型 还可以是个泛型,也可以是具体的数据类型。

    相关文章

      网友评论

          本文标题:swift中泛型的使用

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