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()

Swift泛型定义 同时限定T的类(class)和多协议(protocol)的更多相关文章

  1. Swift泛型协议的N种用法

    They said "you should learn a new language every year," so I  learned Swift. Now  I  learn ...

  2. Java泛型全解析【接口、类、封装类型】

    目录   1.导读  2.为何需要泛型?   3.泛型的定义格式   3.泛型的好处  4.什么时候使用泛型?   5.泛型的擦除   6.泛型的补偿  7.泛型的应用      7.1[泛型类]   ...

  3. 一文详解scala泛型及类型限定

    今天知识星球球友,微信问浪尖了一个spark源码阅读中的类型限定问题.这个在spark源码很多处出现,所以今天浪尖就整理一下scala类型限定的内容.希望对大家有帮助. scala类型参数要点 1. ...

  4. Swift 泛型和闭包结合使用

    通常在Swift中定义一个闭包来使用 typealias Closure= (Any?) -> () var tempClosure :Closure? /// 定义一个方法直接调用 func ...

  5. SpringCloud系列三:SpringSecurity 安全访问(配置安全验证、服务消费端处理、无状态 Session 配置、定义公共安全配置程序类)

    1.概念:SpringSecurity 安全访问 2.具体内容 所有的 Rest 服务最终都是暴露在公网上的,也就是说如果你的 Rest 服务属于一些你自己公司的私人业务,这样的结果会直接 导致你信息 ...

  6. C++之enum枚举量声明、定义、使用与枚举类详解

    C++之enum枚举量声明.定义.使用与枚举类详解 学习一个东西,首先应该指导它能做什么,其次去知道它怎么去做,最后知道为什么去这么做. 知其然知其所以然.不能冒进 ,一步一步的慢慢来.

  7. C++定义一个简单的Computer类

    /*定义一个简单的Computer类 有数据成员芯片(cpu).内存(ram).光驱(cdrom)等等, 有两个公有成员函数run.stop.cpu为CPU类的一个对象, ram为RAM类的一个对象, ...

  8. django-自定义文件上传存储类

    文件储存API:https://yiyibooks.cn/xx/django_182/ref/files/storage.html 编写自定义存储系统:https://yiyibooks.cn/xx/ ...

  9. 系统整理 精讲 swift 泛型

    泛型是一种非常领会的语法,让我很是膜拜! 真是让人又爱又恨,学不懂的时候很抓狂 允许程序在函数,枚举,结构体,类中定义类型形参(类型可以动态改变) 每次使用可以传入不同类型的形参! Array< ...

随机推荐

  1. redis之string数据类型常用方法总结

    目录 redis 字符串(string)[需要掌握] 特点 语法 redis 字符串(string)[需要掌握] 特点 一个键能存储512MB数据 string类型是二进制安全的,可以存储任何数据,比 ...

  2. python 中的富文本编译器

    第一种方式: 1,pip install django-tinymce 2,在INSTALL_APPS里面添加tinymce        在站点中使用: 配置setting.py TINYMCE_D ...

  3. jforum发表文章和回复文章显示中文乱码问题

    jforum安装时,在数据库创建jforum数据库的时候,设置了字符集(CREATE DATABASE jforum DEFAULT CHARACTER SET utf8 COLLATE utf8_g ...

  4. 移动互联网APP测试流程及测试点

    1.2测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日),根据项目情况以及版本质量可适当缩短或延长测试时间.正式测试前先向主管确认项目排期. 1.3测试资源 测 ...

  5. SystemVerilog Assertion 设计、调试、测试总结(3)

    上两篇主要是讲述断言的概念,基本语法,总结等等 这一篇主要是以PPT的形式展示各个场景下关于断言的应用. 为了在设计中加入断言的功能,因此需要写一个DUT.如下: `define `define fr ...

  6. Pyspider的基本使用 -- 入门

    简介 一个国人编写的强大的网络爬虫系统并带有强大的WebUI 采用Python语言编写,分布式架构,支持多种数据库后端,强大的WebUI支持脚本编辑器,任务监视器,项目管理器以及结果查看器 官方文档: ...

  7. GitHub fork 合作开发 - 快速实现版

    目录 一 预备条件 二 fork项目 三 将项目clone到本地 四 push代码到自己的仓库 五 通过pull request提交代码 六 通过本地配置upstream来同步更新主repo的内容 七 ...

  8. IdentityServer4专题之二:OpenID介绍

    1.基于概念 OpenId是一个以用户为中心的数字身份识别框架,它具有开放.分散.自由等特性.OpenId的创建是基于这样一个概念:我们可以通过URI(或者URL网址)来识别一个网站.同样,我们也可以 ...

  9. 十四 数据库连接池&DBUtils

    关于数据库连接池: 1 数据库的连接对象创建工作,比较消耗性能. 2 一开始在内存中开辟一块空间,往池子里放置多个连接对象,需要连接的时候从连接池里面调用, 使用完毕归还连接,确保连接对象能够循环利用 ...

  10. 设备树DTS 学习:2-设备树语法

    背景 通过上一讲了解完设备树DTS有关概念,我们这一讲就来基于设备树例程,学习设备树的语法规则. 参考:设备树详解dts.设备树语法详解.设备树使用总结 设备树框架 1个dts文件 + n个dtsi文 ...