最近在看Casa博客上组件化相关的一些文章,感觉收获很大。
这是他的一个系列文章,有三篇继承、多态、封装。
Casa博客链接
他的意思实际上不是摒弃面向对象的思想,而是指出在部分情况下不要滥用面向对象的模式。
以下是文章的摘录,括号内是个人理解。😄
继承
继承概念:子类自动共享父类数据结构和方法的机制。
其实不是说继承不好,而是要做到不要盲目使用继承。
首先继承的优点是很方便可以做到代码复用,但是这个特性容易在开发中被滥用,从而导致高耦合,变成了父类牵一发而动全身。
需要注意以下几点:
- 解决问题的时候优先使用组合替代继承(组合替代继承,单一职责)
- 继承的时候需要考虑父子类层级之间的职责关系(父类是给子类提供服务,不涉及子类的业务逻辑;层次关系明确,父子类各做各的;父类的所有改动都需要在子类中体现,此时耦合成为了需求)
总结:从目前的开发场景来说,真正用到继承的地方并不多,而使用组合需要比继承更强的抽象能力,这使得我们在开发工作中会下意识的使用更符合直觉的继承,但从长远角度来看,使用组合的好处更多,能够使用组合来实现的就不要使用继承。
多态
多态概念:不同对象接收同一消息可以产生不同结果,多态的本质是子类覆盖或重载父类的方法,使得调用同一类对象的同一方法产生不同效果。
在这里讨论的是以下几种情况如何去解决:
- 父类有部分public的方法是不需要,也不允许子类覆重(比如业务的固定调用顺序。这里不允许子类覆重如何实现?)
- 父类有一些特别的方法是必须要子类去覆重的,在父类的方法其实是个空方法(如何保证子类的实现者不会忽略必须要重载的方法)
- 父类有一些方法是可选覆重的,一旦覆重,则以子类为准
- 父类有一些方法即便被覆重,父类原方法还是要执行的(而且需要保证一定的调用顺序)
作者给出的解决方案是使用IOP。
父类中预留子类child作为属性,协议公开需要或可选覆重的方法,自己可以不实现,子类必须实现协议,父类中直接调用child对应方法。即可解决以上问题。
1.通过约定,public方法一般不允许覆重,可以覆重的是协议中的方法
2.协议中的require方法都是子类必须覆重的
3.协议中的optional方法都是子类可选覆重的
4.父类在想要调用的地方调用child的对应方法(此时子类的对应方法中不能调用父类的super的同方法,否则会死循环)
当然,滥用子类多态可能会导致类的功能不单纯,实际上在工作中,不要再覆重方法中执行与方法本意不相关的逻辑,需要判断此处是否真的需要多态,把可以不用多态的地方,可以使用IOP,提高代码的可移植性。
封装
概念:隐藏对象的属性及实现细节,仅对外公开接口。
这篇文章中主要讨论的是数据结构和函数实现是否应该连在一起的问题。(在去model化这篇文章中也讨论了数据结构应该怎么处理的问题)
观点是不是所有的东西都需要专门封装成对象,函数只需要它需要的参数即可,如果尽可能所有的数据都有一个普适的容器用来传递(如实现某协议的id,dic之类),这样就能做到降低耦合。而且这样做是更加倾向与组合而不是继承,可以避免很多不恰当的继承。
具体做法:
1.字典
2.IOP
总结:面向对象在架构设计时是一种非常好的程序设计思想,但是如果将其简单的映射到程序实现上来,可能会有水土不服的情况。