• Swift泛型定义 同时限定T的类(class)和多协议(protocol)


    https://blog.csdn.net/weixin_34054931/article/details/88027728

    swift 可以定义模板函数,如:

    func testFunc<T>(datas: [T]) -> T{

    //处理 

    复制代码

    这里有个T,使用指代类型的,这个方法定义出来,可以用来处理任意的数组:

     

    let names = [String]()

    testFunc(names)
    let names2 = [Int]()

    testFunc(names)

    复制代码

    传入String的数组,T就是String;传入Int的数组,T就是Int.这个方法就像是一个模板,有了它,可以复刻出许多个不同的版本。

    问题1:我想要这个T是具有某个特定方法的

    举个常用的例子:

    比如写一个用来找最小值的方法,func min<T>(datas: [T]) -> T?,我肯定是希望它能处理数字、字符串、日期,甚至是自定义类的对象,那就需要这个被排序的数组里的对象,必须得实现一个比较的函数, 这个我才能知道那个大那个小,才能排序。而且我只需要这个比较函数就可以对所有类通用了。

    比如可以写成:

     

    func min<T>(datas: [T]) -> T?{

      if datas.count == 0 {
        return nil

      }

      var min: T = datas.first!

      for data in datas {

        if data.compareTo(min) < 0{

          min = data

        }

      }

      return min

    }

    里面用了compareTo方法。我要怎么确定这个T一定是有这个方法的呢?

    祭出法宝:protocol

    联想:一些人困惑协议有什么用?跟block/闭包有什么区别?这里的功能就是闭包无法替代协议的,其实协议和委托是可以不一起行动的。

    定义一个协议:

     

    protocol Comparable : NSObjectProtocol{

    /**
    和其他对象比较

    - parameter other: 其他对象

    - returns: 0 相等 -1 小于 1 大于

    */

    func compareTo(other: Self) -> Int

    }

    复制代码

    然后把方法定义修改为:

     

    func min<T:Comparable>(datas: [T]) -> T?

    复制代码

    T后面限定了类型,指定了这个T是遵循类Comparable这个协议的,那么也就具有了compareTo这个方法。在我理解里,协议的核心就在这:表明某个类具有特定的方法/能力

    问题2:多个协议怎么办?

    假如我想处理的T类型是需要具有两个不同的能力,举个现实的例子:一个榨汁机,它接收的东西应该同时具有可被碾碎和出水两个特性,这两个特性是分开的,因为饼干不出水和椰子碾不碎。对应到代码,可悲碾碎是一个protocol里的一个方法,会出水是另一个protocol的方法。

    多个协议只需要写成:

     

    func min<T:protocol<testProtocol1,testProtocol2>>(datas: [T]) -> T?

    复制代码

    把两个协议用protocol关键字装起来就好了。

    问题3:如果我还想这个T是某个特定的类呢?

    比如我想T是class1这个类的对象,同时遵循testProtocol1和testProtocol2,怎么写?

    祭出法宝:where关键字

    方法写成:

     

    func findMinTemplateFunc<T : testCalss

    where T :protocol<testProtocol1,testProtocol2>>(datas: [T]) -> T?

    复制代码

    把协议的限定方法where里面去,where还有其他用法,我也没太用过,就不说了。

    这个需求看起来好像很难发生,但只需要想一个东西就有了:抽象类。swift/OC里没强掉这个概念,但是这个东西是存在的,比如CoreData里面的NSManageredObject,你会直接使用这个类来构造对象吗?肯定不会,肯定要建自己的数据实体,也就是NSManageredObject的子类来操作了。

    当有了抽象类做父类的时候,你处理的都是子类,如果你写一个针对子类的模板方法,有些子类实现了testProtocol1,有些实现了testProtocol2,有些没有。这时,就必须类、协议同时限定才能达到效果。

    最后贴段例子:

    加入找出数组里最小值,每个值根据value1 value2 和rate做一段算法后的值来比较:

     

    protocol testProtocol1: NSObjectProtocol {

        func value1() -> Int;
    }

    protocol testProtocol2: NSObjectProtocol {

        func value2() -> Int;

    }

    //类似虚类的东西,比如NSManagedObject这种类,是不可能直接使用它来构建对象的,肯定是要配合自己建的CoreData实体

    class testCalss: NSObject {

        var rate: Int? = 1

    }

    func findMinTemplateFunc<T : testCalss where T :protocol<testProtocol1,testProtocol2>>(datas: [T]) -> T?{

        if datas.count == 0 {

          return nil

           }

        var min : T = datas.first!

        var minRealValue = min.value1() * 10 + min.value2() * 100

      if let rate = min.rate {

            minRealValue *= minRealValue * rate

        }

      for data in datas {

            var realValue = data.value1() * 10 + data.value2() * 100

        if let rate = data.rate {

                  realValue *= realValue * rate

              }

      if realValue < minRealValue {

                min = data

                minRealValue = realValue

            }

        }

    return min

    }

    //例子

    class subClass1: testCalss, testProtocol1, testProtocol2 {

        func value1() -> Int {

        return Int(arc4random() % 10)

        }

        func value2() -> Int {

        return Int(arc4random() % 20)

        }

    }

    class subClass2: testCalss, testProtocol1, testProtocol2 {

        func value1() -> Int {

        return Int(arc4random() % 100)

        }

        func value2() -> Int {

        return Int(arc4random() % 200)

        }

    }

    func runTest(){

        var array1 = [subClass1]()

        for _ in 0...99 {

                array1.append(subClass1())

            }

        findMinTemplateFunc(array1)

          var array2 = [subClass2]()

        for _ in 0...99 {

              array2.append(subClass2())

          }

        findMinTemplateFunc(array1)

    }

    runTest()

  • 相关阅读:
    javascript 面向对象 new 关键字 原型链 构造函数
    前端性能优化之gzip
    电子商务秒杀所带来的问题
    git 远程版本库,github提供服务原理,git自动更新发送邮件
    单点登陆的三种实现方式(详解)
    使用php实现单点登录
    支付宝异步回调
    http状态码大全
    php 单向散列加密
    curl模拟post请求
  • 原文地址:https://www.cnblogs.com/sundaysme/p/11775414.html
Copyright © 2020-2023  润新知