分类(category)、类的扩展(extension)、协议(protocol)特点及应用场景
分类特点
- 分类是用于给原有类添加方法的,因为分类的结构体指针中,没有属性列表,只有方法列表。
- 如果分类中有和原有类同名的方法, 会优先调用分类中的方法, 就是说会忽略原有类的方法,同名方法调用的优先级为 分类 > 本类 > 父类
- 如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定;编译器会执行最后一个参与编译的分类中的方法。
- 分类可以有多个,也就是一个类可以有多个分类
- 运行时决议,同名分类方法生效取决于编译顺序
- 名字相同的分类会引起编译报错
分类的用途
- 可以为系统的类添加我们想要的方法。
- 多人合作时,由于功能的不同可能需要多个不同的方法,我们只需创建一个类,每个人分别用类别的方法去为类添加自己需要的方法,这样节省开发时间,出错率也很小。
类的扩展特点
- 声明私有属性
- 声明私有方法
- 声明私有成员变量
- 编译时决议
- 只以声明存在,寄生于宿主类.m中
- 不能为系统类添加扩展
分类、扩展区别
- 分类中原则上只能增加方法(能添加属性的的原因只是通过runtime解决无setter/getter的问题而已);
- 类扩展不仅可以增加方法,还可以增加实例变量(或者属性),只是该实例变量默认是@private类型的(
用范围只能在自身类,而不是子类或其他地方); - 类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
- 类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。
- 定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。
OC协议以及协议的使用
- 因为继承的耦合性强,并且oc是单继承的,所以协议就应用而生,协议是一系列标准的方法列表,可以被任何类实现。
- 协议中不能声明成员变量,只要一个类遵守了这个协议,也相当于拥有了该协议中所有方法的声明。
- 根据继承的规则,只要父类遵守了该协议,那么它的子类也就都遵守该协议,并且一类中可以遵守多个协议,最常用的就是UITableView啦,遵守了UITableViewDelegate, UITableViewDataSource两个协议
- 协议中有两种情况,一种是必须要实现的required,一种是可选择实现optional。
- 一个协议可以遵守其他的多个协议,相当于他用了其他协议方法的声明。
- 可以定义对象的时候,限制这个类去遵守这个协议。
Swift协议及特性
swift与OC协议共同点
- 本质都是抽取不同类的共同方法和属性(声明),供遵循协议的类或对象使用。
- 都可以通过定义协议实例deleagate,来实现委托代理模式。
swift与OC协议区别(核心)
OC协议
- OC协议更单纯的受限于委托代理的含义,多用于跨类的传值和回调通知。
swift协议
- Swift可以通过协议 extension 扩展,缺省实现协议的方法(OC不行)。
- 定义属性方法
- Swift是面向协议编程,其思想是通过抽取不同类中的相同方法和属性,实现模块化减少耦合。
- Swift的协议不需要单独声明协议对象(**id delegate **)和指定代理( delegate = self ),只需要遵循协议的类实现声明,或使用协议的缺省实现。
为何说Swift是面向协议协议编程?
- 传统的协议(比如Objective-C的protocol)只能定义接口,不能复用实现,遵守同一个协议的不同的类,只能分别实现协议接口,使用场景受限了很多。
- Swift只是多了一个协议扩展的特性,但却带来了编程范式的进化。
面向协议编程(POP)与面向对象编程(OOP)
面向协议编程(简称 POP)定义
面向协议编程是在面向对象编程基础上演变而来,将程序设计过程中遇到的数据类型的抽取(抽象)由使用基类进行抽取改为使用协议(Java语言中的接口)进行抽取
区别
面向对象编程(简称OOP)定义
面向对象顾名思义就是把现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装。OOP的三大特性:封装、继承、多态
特点区分
- 面向对象编程使用类和继承的手段,数据类型是引用类型;
- 面向协议编程使用的是遵守协议的手段,数据类型是值类型(Swift中的结构体或枚举)。
总结
Swift是一门支持多编程范式的语言,既支持面向对象编程,也支持面向协议编程,同时还支持函数式编程。在项目开发过程中,控制器和视图部分由于使用系统框架,应更多采用面向对象编程的方式;而模型或业务逻辑等自定义类型部分,则应优先考虑面向协议编程。
if let 与 guard let 用法
if let 用法
- 普通if与if let的比较,如果常量是可选项(Optional),if判断后仍然需要解包(!)
let name: String? = "mike"
let age: Int? = 10
if name != nil && age != nil {
print(name! + String(age!)) // 输出: mike 10
}
- 如果常量是可选项(Optional),if let判断后不需要解包(!),{ }内一定有值
let name: String? = "mike"
let age: Int? = 10
// if let 连用,判断对象的值是否为'nil'
if let nameNew = name,
let ageNew = age {
// 进入分支后,nameNew 和 ageNew 一定有值
print(nameNew + String(ageNew)) // 输出: mike 10
}
- if var的用法,和if let的区别就是可以在{}内修改变量的值
let name: String? = "mike"
let age: Int? = 10
if var nameNew = name,
let ageNew = age {
// 'var'修饰,可以修改'nameNew'的值,'let'修改的不可以修改
nameNew = "nero"
print(nameNew + String(ageNew)) // 输出: nero 10
}
guard let用法
- guard let和if let刚好相反,guard let守护一定有值。如果没有,直接返回。
- 通常判断是否有值之后,会做具体的逻辑实现,通常代码多
- 如果用 if let凭空多了一层分支,guard let是降低分支层次的办法
- guard let语法是 Swift 2.0 推出的
let name: String? = "mike"
let age: Int? = 10
guard let nameNew = name,
let ageNew = age else {
print("姓名 或 年龄 为nil")
return
}
// 代码执行至此, nameNew 和 ageNew 一定有值
print(nameNew + String(ageNew)) // 输出: mike 10
网友评论