Swift面向协议编程总结

96
一蓑烟羽
2017.11.13 15:27* 字数 1136

Swift面向协议编程

所谓面向协议编程,就是使用protocol声明方法,然后使用extension提供默认的实现,只要需要使用到该方法的类遵循该protocol,就可以直接使用该extension的实现。

protocol animal {
    var food: String {get}
    func eat()
}

extension animal {
    func eat() {
        print("food name is \(food)")
    }
}

struct Cat: animal {
    
    var food: String = "mouse"
}

struct Dog:animal {
    var food: String = "cat"
}

let cat = Cat()
let dog = Dog()
cat.eat()
dog.eat()

log:
food name is mouse
food name is cat

代码复用

  • 继承:会带来耦合。
    • 继承的代价:这并不是一个新颖的话题,自面向对象编程诞生之日起就饱受争议,我们经常要忍受着愈加繁杂和庞大的继承体系来获得代码的可重用性,而且随着继承层次的增加,代码的复杂性会加速增长,随之而来的bug也会越来越难以发现。这时我们可能需要依靠设计模式来找回我们的思路,然而大多数设计模式只能帮助你理顺你的代码结构,却在同时更加加深了你的代码的复杂度。
  • category/extension:会污染所有的类
  • 面向协议编程protocol+extension 最大程度地减少了耦合

面向协议编程的好处

面向协议编程的好处在于,通过协议+扩展实现一个功能,能够定义所需要的充分必要条件,不多也不少。这样就最大程度减少了耦合。使用者可以像搭积木一样随意组合这些协议,写一个classstruct来完成复杂的功能。实际上,Swift的标准库几乎是everything is starting out as a protocol

为什么说Swift是面向协议编程的语言?

因为Swift里更推荐使用值类型变量(struct)而不是引用类型(class)的变量,Swift中许多常见的数据类型、字符串、集合类型,以及结构体和枚举都是值类型而非引用类型,值类型的变量在赋值时会自动进行一次低消耗的值拷贝,对比对象的copy要更加高效而且不存在线程安全问题。

为什么需要struct

structclass的主要区别:

  • struct是值引用,而class是类型引用
  • struct没有继承的功能,class有继承功能

struct和class这两个基本层面的区别,体现了区别于Objective-C语言,swift语言带来了全新的天翻地覆的改变。

首先说第一点区别,从swift的更新和struct不断完善来看,苹果公司更加推荐使用struct来代替class,因为struct值引用和class类型引用这点区别,保证使用struct编码能写出更加安全可靠的代码。为什么这样说呢,class类型引用在赋值时是将变量指向了同一块内存地址,这在一个长时间的跨度上会带来一些意想不到的问题,试想一个简单的例子,viewControllerA持有一个NSMutableArray数组mutalbeArray,它包含100条user信息,此时将mutableArray赋值给viewControllerB,对于viewControllerB而言,它仅仅需要前10条user信息,所以它将mutableArray多余的信息删除了,这样一个脑残的操作导致了viewControllerA模块展示错误和潜在的逻辑错误。而使用struct值引用则不会出现这样的问题。

第二点区别,struct没有继承的功能,这是因为swift在本质上来说是面向协议(Protocol Oriented)的语言,struct没有也不需要继承的功能,为了实现某个功能,struct去服从并实现某个协议就即可,从一个较高的层次来看,struct+protocol是构成swift面向协议语言的两个基石。

总结

Swift是一门支持多编程范式的语言,既支持面向对象编程,也支持面向协议编程,同时还支持函数式编程。在项目开发过程中,控制器和视图部分由于使用系统框架,应更多采用面向对象编程的方式;而模型或业务逻辑等自定义类型部分,则应优先考虑面向协议编程。

参考文章

Swift面向协议编程(附代码)

谈谈Swift面向协议编程

从 Swift 的面向协议编程说开去

Swift面向协议编程初探

iOS技术干货
Web note ad 1