关于“幽灵架构”的补充说明1:协议中的方法定义
承接上一篇博文,上一篇的篇幅有点太长了,我觉得有一些相关的技术点需要说明,所以重新写几篇博文。这个系列的文章将要说明以下几个问题:
1.giveData和getData在各自协议中的位置
2.使用struct代替class的好处
3.“幽灵架构”为什么不会产生循环引用
4.协议的应用场景与局限性
5.运用面向协议编程思想改造控制器
让我们来简单回顾下这个架构,如果不明白的可以参考上一篇博文:
核心只有两个协议:
//视图使用的协议
protocol ViewType{func getData<M:ModelType>(model:M)
}
//数据使用的协议
protocol ModelType{
}
//定义默认方法giveData
extension ModelType{func giveData<V:ViewType>(view:V){view.getData(self)}
}
首先来回答第一个问题,为什么getData被定义在协议ViewType的定义中,只有函数声明没有实现,而giveData被定义在ModelType的扩展中,并且附带了方法的具体实现。请看下面的例子:
protocol SharedString{
}extension SharedString{func methodForOverride(){print("(。•ˇ‸ˇ•。)")}func methodWithoutOverride(){print("------")methodForOverride()print("------")}
}
两个方法都被定义在了协议的扩展中,现在让String遵守该协议,String将免费获得这两个方法的实现,并且在String的扩展中重写methodForOverride()的实现,输出String本身的值:
extension String:SharedString{func methodForOverride(){print(self)}
}
现在使用字面量生成一个String类型,然后调用方法methodForOverride:
"hello".methodForOverride()
输出的结果是“Hello”,这符合我们的预期,这里使用字面量生成了一个实例,依靠了类型推断的默认值,“Hello”是Sting类型的,也就是SharedString的具体遵守者,所以调用了被重写的methodForOverride版本。Swift中的方法重载不仅可以根据参数进行重载,还可以根据返回值类型进行重载,只需要修改返回值的声明即可。这里我们修改“hello”的上下文:
//用一个字面量来跟大家打个招呼
"hello".methodForOverride()
//hello是SharedString类型的
let hello:SharedString = "hello"
hello.methodForOverride()
hello是SharedString类型的,虽然hello和“hello”的字面量是相同的,打印结果如下:
有趣的是在协议的扩展中声明的方法定义会被保留,更有趣的是另一个方法methodWithoutOverride(),这个方法在方法体中调用了另一个方法methodForOverride,现在对“hello”和hello调用方法methodWithoutOverride:
"hello".methodWithoutOverride()
hello.methodWithoutOverride()
结果如下:
结果有点出乎意料,虽然我们在协议遵守者的定义中重写了方法methodForOverride,定义在协议扩展中的另一个方法只会使用methodForOverride的默认版本的实现,这是协议扩展的静态特性。现在把methodForOverride的声明从协议的扩展中挪到协议的声明中:
protocol SharedString{func methodForOverride()
}extension SharedString{func methodForOverride(){print("(。•ˇ‸ˇ•。)")}func methodWithoutOverride(){print("------")methodForOverride()print("------")}
}
现在无论你使用“hello”还是hello调用methodForOverride()和methodWithoutOverride()都只会输出重写后的结果。
结论:把需要被重写的方法声明在协议的声明中是一种刻意的做法,我们希望该方法被重写,回到架构上,getData负责不同的View处理获得的Model,View的类型非常多,所以getData的格式无法统一到一个默认的方法实现中,我们需要getData被具体的View所重写,为了强制这种意图,getData甚至没有一个默认的实现方法体。根据Swift的协议规则,协议遵守者需要实现协议中的所有方法,所以getData一定会有具体声明。而前文也总结过,对于ModelType中的giveData这个方法的功能非常统一,即向View传递Model,所以统一到同一个方法实现中,并且我们不希望这个方法被重写,因为重写会破坏getData中的逻辑,所以把方法声明写在了协议的扩展中。
最后需要说明的是“幽灵架构”这个名字只是想表达代码隐形的愉悦,其实名字本身并不重要。
关于“幽灵架构”的补充说明1:协议中的方法定义相关推荐
- 从零学习 InfiniBand-network架构(十) —— IB协议中全局ID
从零学习 InfiniBand-network架构(十) -- IB协议中全局ID
- 从零学习 InfiniBand-network架构(七) ——IB协议中数据如何传输
从零学习 InfiniBand-network架构(七) -- IB协议中数据如何传输
- 从零学习 InfiniBand-network架构(九) —— IB协议中子网本地地址
从零学习 InfiniBand-network架构(九) -- IB协议中子网本地地址
- 从零学习 InfiniBand-network架构(一) —— IB协议中常用术语及定义
从零学习 InfiniBand-network架构(一) -- IB协议中常用术语及定义
- 关于“幽灵架构”的补充说明4:协议的应用场景与局限性
再次解释一下协议的意义:定义某个功能模块的最小粒度,因为Swift是单继承,而无论是值类型还是引用类型都可以遵守多个协议,因此协议是比父类的粒度还要小的功能模块.协议的功能定义一定要具体并且严格,so ...
- 关于“幽灵架构”的补充说明3:为什么不会产生“循环引用”
承接上文,已经简明阐述了使用Struct代替Class的好处,使用Class会使我们的程序出现"意外的共享"以及"循环引用"之类的危险,传统面向对象开发中对Cl ...
- 关于“幽灵架构”的补充说明5:改造控制器
Swift中的泛型有非常多的用处,除了我在之前介绍的方法中作为占位符之外,还可以被用在协议中,构成一个泛型协议,那么遵守这个泛型协议的成员就会变成泛型成员.还用我们之前的事件节日提醒Demo来展示,在 ...
- Http协议中的方法
http://blog.csdn.net/macroway/article/details/1428541 孟岩老师将"REST"称为一场Web开发思想的变革,而就我个人理解而言, ...
- 『mcse 2008基础架构』Chapter 01 IP协议及配置方法 第1课网络连接及配置方法
学习目标: 理解TCP/IP协议组中的4个层次 查看和配置本地网络连接的IP设置 理解网络广播的概念 使用TCP/IP工具排除网络连通性故障 转载于:https://blog.51cto.com/ld ...
最新文章
- SUSE10中Oracle10g存储中文数据
- 皮一皮:不是很懂他的精神追求,有懂得来解释下...
- 获得AndroidManifest.xml文件中meta-data的value值
- docker安装Elasticsearch
- 没有密码直接进入mysql
- springboot实现上传文件
- wxWidgets:wxPlatformInfo类用法
- 最全的BAT大厂面试题整理,系列篇
- 小学数学加减法测试软件,儿童数学加法运算火箭(测试版)
- GMTC2019|闲鱼-基于Flutter的架构演进与创新
- contains()+replaceFirst()进行substring计数(洛谷P3741题题解,Java语言描述)
- 系统架构设计上需要注意的
- c# xls 复制一行_c# – 将excel工作簿中的第一行复制到新的Excel工作簿
- java trim all,[JAVA中各种去除空格][java string.trim()][str.replaceAll去空格]
- 5-3 面向可维护性的构造技术
- 局域网共享工具_局域网共享精灵 V1.0局域网便携共享文件+打印机——墨涩网
- 电脑数据传输哪款软件好用?
- Hexo博客使用友盟+CNZZ统计页面访问次数
- win10打开红警卡死的解决方法--win10专业版
- openGL中Phong 着色