04-17.eri-test Java周二生效! 偏爱继承而不是继承

今天,我们开始着手研究面向对象编程的核心项目之一。特别是继承的危险以及在许多情况下哪种更好的方法。继承是正确使用面向对象的强大和核心功能。我们将在此博客文章中讨论的是一种特殊的模式,该模式为我们提供了一些继承功能,同时又使我们保持安全并维护封装。

首先,有两种不同类型的继承。首先是<Ëm>实现继承Ëm>这是一类的扩展,扩展了另一类的功能。这是我们将在此博客文章中讨论的继承类型。也有接口继承其中一个类实现一个接口,或者一个接口扩展另一个接口。此博客文章未涉及第二种继承类型。

这篇博文标题的核心是继承破坏了封装。问题在于,对超类的更改可能导致子类出现问题,而子类却没有意识到。这可能会导致损坏,意外的数据泄漏以及其他最好避免的问题。这意味着子类需要与其父类同步发展,否则可能会遇到问题。

让我们看一个示例,尽管人为设计,但本书中的示例确实可以显示问题。该示例类背后的想法是,它为用户创建了一种具有哈希集Øde>可以检索将项目添加到其中的次数。让我们来看看。

@NoArgsConstructor上市类Instrumented哈希集<Ë>延伸哈希集<Ë>{@盖特私人的整型加Count=0;上市Instrumented哈希集(整型在itCap,浮动loadFactor){超(在itCap,loadFactor);}@Override上市布尔值加(Ëe){加Count++;返回超。加(e);}@Override上市布尔值全部添加(采集<?延伸Ë>c){加Count+=c。尺寸();返回超。全部添加(c);}}

Thisimplementation,althoughitlooksreasonable,hasanissuethatyouwon'tdiscoveruntilyourealizehow的implementation的Hash组works。Under的hood全部添加简单地打电话插入元素,以便在执行呼叫时myCoolInstrumentedHash组。全部添加(List。of("a","b","c"))你最终得到一个加Countof63就像您期望的那样。在其中添加了三个全部添加通话中添加了3个呼叫。有一些方法可以“解决”此问题,例如删除全部添加调用,但这仍然使其依赖于类的实现。虽然今天可以使用,但明天可以使用吗?

In加ition to the coupling discussed above, there are other issues with using inheritance when it comes to fragility。 As time goes on various things can happen to the 超 class。 It can inherit new abilities with new 方法s, potentially conflicting with the names of 方法s in your subclass, it can expose 整型ernal state that you were depending on controlling the invariants of, and various other issues。

There must be a better way!? Well there is。 Ënter composition。 What in the world is composition? Well simply put, instead of extending a class's functionality a class simply has an instance of that class as an 整型ernal member and it delegates behaviors to it。 This changes the inheritance 与某人的关系有一个关系。 让我们从上面的示例来看一下这是什么样子:

上市 class 仪表台<Ë> 延伸 转发集<Ë> {@盖特私人的 整型 加Count;上市 仪表台<Ë> 包装的 {包装的);}@Override上市 布尔值 addË newËlement {addCount++;addnewËlement);}@Override上市 布尔值 全部添加采集<? 延伸 Ë> newËlements {addCount + = newËlements尺寸();返回 全部添加newËlements);}
}

@RequiredArgsConstructor
上市 class 转发集<Ë> 实施 <Ë> {私人的 最后 <Ë> ;
上市 虚空 明确() {明确();}上市 布尔值 包含宾语 o {  返回 包含o);}上市 布尔值 是空的() {返回 是空的();}上市 整型 尺寸() {返回 尺寸();}
。。。 重复 对于 每一个 method in the  接口.
}

OK what did we just see. We took our one class using inheritance and turned it 整型o two classes without using inheritance but using composition. What did this gain us? It helps us have more robust code. We have isolated ourselves from changes in the individual concrete classes, there is no chance of something changing out from under us because we control the whole 整型erface, etc. We also got some more flexibility. We now take in a of any type (not just Hash组) and can operate on any of them. We can even add the instrumentation after the 已通过其他一些代码初始化。

我们使用上述包装器类的方式称为装饰器图案。 我们将获取一个已经存在的对象,并通过其他行为“修饰”它,同时仍然允许将其用作原始对象。

So nothing is without it's downsides, what are our downsides here? Well the main one should be pretty obvious. We took a pretty small class using inheritance and ended up with two classes and a lot more mind numbing code where we just duplicating an 接口 as we 对于ward on calls. While this is a good chunk of code it's not hard code to write. This is such a solid pattern that languages such as Kotlin build syntactic sugar around making this pattern easier to code up without so much code. You can also reuse these forwarding classes after you have written them. I have also always wondered if you could use Java proxies to generate these forwarding classes at runtime. Make that an exercise for the reader.

继承确实占有一席之地。 当你能真正说出小部件B 小部件那么继承关系就可以了。 如果小部件B相反,只需要具有以下行为小部件那么构图可能就是您所追求的。 老实说,如果您可以摆脱作文,那可能是更安全的选择。 当您使用此模式时,会产生很多健壮性和强大功能,我希望您能够在继续进行开发工作时认识到该模式何时对您有用。

from: https://dev.to//kylec32/effective-java-tuesday-favor-composition-over-inheritance-4ph5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值