美文网首页
iOS -- 分类注意事项 (15)

iOS -- 分类注意事项 (15)

作者: dingzhijie | 来源:发表于2017-09-30 09:50 被阅读0次

(1) 总是为第三方类的分类名称添加前缀

分类机制通常 用于向无源代码的 既有类中新增功能, 这个特性极为强大,但是在使用时也很容易忽视其中可能产生的问题, 这个问题在于: 分类中的方法是直接添加在类里面的, 它们就好比这个类中固有的方法, 将分类方法加入类 这一操作时在运行期系统加载分类时 完成的,运行期系统会把分类中 所有的方法都加入类 的方法列表中, 如果类中 本来就有此方法,而分类又实现了一次, 那么分类的方法会覆盖原来的那一份实现代码, 实际上可能会发生很多次覆盖, 比如某个分类中的方法覆盖 '主实现'中的相关方法, 而另外一个分类中的方法又覆盖了这个分类中的方法, 多次覆盖的结果 以最后的一个分类为准.

要解决此问题, 一般的做法是: 以命名空间 来区别各个分类的名称 与其所定义的方法,,想在OC 中实现命名空间功能, 只有一个办法, 就是给相关名称 都加上某个共用的前缀, 于给类名加前缀类似, 给分类所加的前缀也要选择恰当才行, 一般来说, 这个前缀应该与应用程序 或程序库中其他地方所用的前缀相同.

于是, 我们可以这样写

@interface NSString (ABC_HTTP)

///////

@end

从计数角度将, 并不是非得用命名空间把各个分类的名称区隔开不可, 即使两个分类重名了, 也不会出错, 但是编译器会发出警告.

此外,还要记住, 如果向某个分类中加入方法, 那么在应用程序中, 该类的每个实例方法均可调用这些方法, 比方说, 若是想 NSString, NSArray, NSNumber 这种类中加入方法, 那么这些类的每个实例均可调用你写的这些方法, 不管这些实例是不是 由你的代码创建出来的, 也依然会如此.

如果你无意中把自己分类里的方法名起的和其他分类一样, 或是与第三方库所添加分类中的方法重名了, 那么就可能会出现奇怪的 Bug.

总结: 向第三方类中添加分类时, 总应给其名称加上你专用的前缀.

向第三方分类添加分类时, 总应给其中方法加上你专用的前缀.

(2) 勿在分类中声明属性

属性是数据封装的方式, 尽管从技术上讲, 分类中也可以声明属性, 但是这种做法还是要尽量避免, 原因在于, 除了 'class-continuation 分类'之外, 其他分类 都无法向类中新增实例变量, 因此,他们无法把实现属性所需的实例变量合成出来.

正确做法是: 把所有的属性 都定义在主接口里面, 类所封装的全部数据 都应该定义在主接口里面, 这里是唯一能够定义 实例变量(也就是数据的地方), 而属性只是定义实例变量及相关存取方法所用的 '语法糖',所以也应该遵循同实例变量 一样的规则. 至于分类机制, 则应将其理解为一种手段, 目标在于扩展类的功能, 而非封装数据. 虽说如此, 但是有时候只读属性还是可以在分类中使用的. 但是,最好不要使用.

总结: 把封装数据所用的全部属性都定义在主接口里面.

在'class-continuation 分类之外' 的其他分类里面, 可以定义存取方法, 单尽量不要定义属性.

(3) 使用 'class-continuation 分类' 隐藏实现细节

类中经常会包含一些无法对外公布的方法以及实力变量, 其实这些内容也是可以对外公布,并且写明其为私有, 然而, 我们嘴还还是只把确实需要对外公布的那部分内容公开. 那么,这种不需要对外公布但是应该具有的方法及实例变量应该用 'class-continuation 分类' 来写.

'class-continuation 分类' 和普通的分类不同, 它必须定义在其所接续的那个分类的实现文件里面,其重要之处在于, 这是唯一能声明实例变量的分类, 而且此分类没有特定的实现文件, 其中的方法都应该定义在类的主实现文件里面, 与其他分类不同, 'class-continuation 分类' 没有名字, 比如, 有个类叫做 EOCPerson, 其'class-continuation 分类' 写法如下

@interface EOCPerson ()

// Methods here

@end

为什么需要有这种分类呢, 因为其中可以定义方法和实例,

这样做有什么好处呢, 公共接口里面本来就能定义实例变量, 不过,把他们定义在 'class-continuation 分类' 或 '实现块' 中可以将其隐藏起来, 只供本类使用

总结:

通过 'class-continuation 分类' 向类中新增实例变量

如果某属性在 主接口中声明为 '只读',而类的内部又要用设置方法修改此属性, 那么就在 'class-coninuation 分类' 中将其扩展为 '可读写'

把私有方法的原型声明在 'calss-coninuation 分类' 里面

若想使得类所遵循的协议不为人所知, 则可与 'class-continuation 分类' 中声明

相关文章

网友评论

      本文标题:iOS -- 分类注意事项 (15)

      本文链接:https://www.haomeiwen.com/subject/rzkgextx.html