作者爱说话
Hello,大家好,我是 行云
这是原创的第 10 篇文章,希望今天这篇文章能带给你一点思考和启发
前阵子听朋友说,什么垃圾垃圾公众号文章,我说咋了,他说微信公众号推的啥,“面试阿里 P7 岗,第六题就被干掉”、“十年码农面试,被微服务坑惨了,真实经历”、“新来的同事把项目性能优化了一遍,看看他是怎么做到了?”
因为我也写微信公众号,我听到这些文章,我就觉得,应该是“恰饭”文章,我不反对“恰饭”文章,因为不管每一篇文章质量如何,只要是原创的文章,后面必定是作者用心的输出,只要是有用心的付出都必定希望得到一些正反馈,无论是粉丝、阅读量、亦或是接一些这种广告,这些都是无可厚非的行为
但是这种带诱惑性质标题的文章会让人感觉不太舒服,就比如你满心期待掀起的头盖里是倾国倾城的美女,结果掀开发现是这(本来想贴贴图片,但是感觉贴网上图片也不太尊重人,哈哈哈,读者自行脑补),多少都会有点失望,然后像我的朋友那样带点被骗的感觉,取消公众号的关注,这对公众号也是得不偿失吧,我觉得每一个公众号的主人写文的初心都不是为了赚钱吧
话又说回来了,如果不带这种带诱惑性质标题的文章,估计阅读量翻车的时候,金主爸爸,马*兵老师要不开心了,至今还在微信公众号圈外的我,无法体会这种纠结的感觉
何为继承?
王经理:今天我来给你们讲一讲使用继承的正确姿势,我们都知道,Java 是一种面向什么编程的语言?
林步动:我知道,我知道,是面向工资编程 ?
王经理:? 小林,你今年 3.25 没跑了
小美:是面向对象编程
林不动:对象是这样的吗?
王经理白了一眼林步动后:
面向对象的编程语言,具有三大特性,继承、封装、多态
首当其冲的就是继承,以一个类(父类,基类)作为基础,复制它,然后通过添加和修改这个副本(子类)来创建新的类,这就是继承做的事。 继承是面向对象编程中,不可或缺的一部分。它使我们的代码富有层次感,也为多态打下了结实的语法地基
但是可以多继承吗?就是一个类继承多个父类?
林步动:当然不可以,那么多父类,儿子都不认识谁是真正的爸爸了
王经理:对,对于继承可能还会有这样的一个争论,“继承应该只覆盖基类的方法(而并不添加在基类中没有的新方法)” ,但是往往来说,继承是个“is - a”关系,如何衡量你的继承是否是正确的,就是看你的继承是否满足 LSP(里氏替换原则),简单来说,就是任何父类可以出现的地方,子类都能够出现
林步动:太抽象了,我来举个例子给小美听
小美:不用啊,我能听懂
林步动:不,你不懂。
继承是个“is - a”关系“,意思就是,妈妈叫我们去买水果,我们买回来苹果是可以的,买回来香蕉也是可以的,但是我们买回来的是薯片、可乐、汉堡、辣条就不行,会被妈妈打,在实际代码环境中,如果父类引用直接使用子类引用来代替,可以编译正确并执行,输出结果符合子类场景的预期,那么这两个类之间就符合 LSP,就可以完美的使用继承
你乱用继承了吗?
王经理:小林说的还是有点道理的,因为继承使用起来非常的方便快捷,我们在撸代码的时候,突然看到,这个父类有我们想要的东西,第一反应,不用造轮子了,继承它,奥利给。所以继承就像保健品一样,被我们乱吃,乱用 ,但是
所以我们需要对继承有个“敬畏”之心,认清错误使用继承会造成什么样的后果
小美:我知道经理,乱用继承,会造成方法污染,比如鸟会飞,不能因为鸵鸟带个鸟字,就让鸵鸟继承鸟,发现鸵鸟不会飞,只会把头埋进土里
子类一旦要继承父类,就说明子类可以肆无忌惮的调用父类的一切方法,我们不能强迫鸵鸟学会飞翔,所以对是否可以继承得有一个清楚的认知
林步动:我也知道经理,乱用继承,会造成方法爆炸?,比如一个父类非常受欢迎,它的儿子也非常受欢迎,它的孙子也非常受欢迎,它的曾孙子也非常受欢迎,不断地继承后达到了几百代同堂(具有几百个方法),对于具有选择综合症的人,这个方法可以实现我想要的功能,那个方法也可以实现我想要的功能,不对,另一个方法也可以,造成了使用不便和安全隐患
王经理:对,有些场景下,其实优先采用组合或聚合关系来复用其他类的能力,或许是一个更好的选择,《Effective Java 中文版第2版》书中第16条中也说到:继承是实现代码复用的有力手段,但它并非永远是完成这项工作的的最佳工具。
组合关系
王经理:组成其实是一种 "belong-to" 的关系类型。这意味着其中一个对象是逻辑上较大的结构,其中包含另一个对象。换句话说,它是其他对象的一部分或成员。 或者,我们通常称之为"has-a"关系
林步动:就是聚合是体现的是整体与部分、拥有的关系(这不是哲学),即has-a的关系
看下面一段代码:
public class Package {
// 钱包里有许多钱
private List<Money> money;
// ...
}
在代码层面,聚合可以看作,一个钱包里可以有许多钱 ,但是钱包里不一定有许多钱,因为可能是个穷光蛋的钱包
has-a 不是 必须 has,钱包是可以整体,钱是个部分,可以分离开,他们都具有他们自己的生命周期
组合关系
王经理:
组合体现的是一种 contains-a 的关系,这种关系比聚合更强,也称为强聚合。
先看一段代码:
public class Nose {
private Eye eye = new Eye(); //一个人有鼻子有眼睛
private Nose nose = new Nose();
// ....
}
组合同样是整体与部分的联系,但此时整体与部分不可分割,就像中国与台湾一样,如果整体的生命周期结束也就意味着部分的生命周期结束。
就像正常人有鼻子有眼睛,如果人一旦 die 了,鼻子和眼睛的生命周期也会结束,而且,鼻子和眼睛不能脱离人单独存在
继承还是组合?
事物的存在即有它的道理
继承和组合都是实现系统功能重用,代码复用的最常用的有效的设计技巧
很多人都知道面向对象中有一个比较重要的原则『多用组合、少用继承』或者说『组合优于继承』,组合确实比继承更加灵活,也更有助于代码维护,在需求可以实现的相同情况下,优先使用组合而不是继承
因为组合更安全,更简单,更灵活,更高效,让我们不得不爱上它
但是不能片面断定继承就一点用都没有了,前面说的是【在同样可行的情况下】。有些场景还是需要使用继承的,或者是更适合使用继承。
继承要慎用,其使用场合仅限于你确信使用该技术有效的情况。
一个判断方法是,问一问自己是否需要从新类向基类进行向上转型。如果是必须的,则继承是必要的。反之则应该好好考虑是否需要继承。
只有当子类真正是超类的子类型时,才适合用继承。换句话说,对于两个类A和B,只有当两者之间确实存在 is-a 关系的时候,类 B 才应该继承 类A
参考文章:
《Effective Java 中文版第2版》
《码出高效》
重新认识java - Sharember
我是 行云,原创不易,点个赞再走吧,我们下期再见 ?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。