偶尔我会遇到关于继承在企业应用程序架构中“过时”的评论,但我没有看到描述竞争理论的文章的链接。此外,如果应用程序已经构建而不是从头开始,那么在实现上是否存在差异?我认为这可能与严重依赖接口有关,但我不确定。
7 回答
我认为您指的是设计原则:
“偏好组合胜于继承。”
一个非常流行的继承替代方法(如子类化)是对象组合和委托。
所以而不是
public class B extends A implements I {
// now I have all the methods from A
}
你做
public class B implements I {
private I a;
// delegate all methods
public void methodOne(){
a.methodOne();
}
}
组合比子类化更灵活:
- 您可以拥有多个委托(与只有一个超类相反,至少在 Java 中)
- 它干净地将接口与实现分开(而对于超类,您可以获得它的方法及其实现,甚至是不在接口中的方法)
- 您可以在运行时通过配置交换委托(而超类实例已编译)。依赖注入建立在此之上。
继承不是一种风格
它是一个工具
作曲也是如此
每当我读到这样的笼统信件时,我都会想:
十字螺丝比平头螺丝好。
当您需要钉子或焊缝时,两者都不好,当您知道自己在做什么时,两者都可以。
两者之间的区别是明显而简单的 - “is-a”与“has-a” - 虽然组合可用于模拟继承(需要大量额外工作),但通常情况并非如此。这不是反对继承的论据,也不是组合的论据。
模型的语义远比用来表示它的机制重要得多。说“爬行动物有动物,用委托来暴露它的方法和属性”,而不是“爬行动物是动物的一种”,这很愚蠢,不是吗?那么,为什么不必要地对一个对象做同样的事情而不是愚蠢呢?
继承非常有用,并且是面向对象编程的基础。在更好的事情出现之前它不会消失,而且我还没有发表过;-)
[让火焰开始燃烧吧!]
Smalltalk 和 Perl 中还有 Traits 和 Roles。它们让您重用功能。看看这篇文章。
Allen Holub在本文中描述了实现接口如何优于子类化。虽然这是在 2003 年写的,但它仍然是主题。有趣的是,有一堆 2009 年的评论!
如果您使用的是 C++,那么您应该认真考虑使用 mixins(注意:其他一些语言声称支持某种形式的 mixins):
Wikipedia: http://en.wikipedia.org/wiki/Mixin
Dr. Dobbs: http://www.ddj.com/cpp/184404445.
更有趣的是“奇怪重复的模板模式”(CRTP):
Wikipedia: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern.
我认为 CRTP 是一个非常有用的 mixins 应用程序。
一旦你“得到它”(这需要一段时间),你就会意识到 mixins 非常强大。它们为您提供了一种代码重用方法,该方法不会遇到继承重用的问题,但比使用组合和委托更灵活、更高效。
有趣的是,CRTP 允许您模拟虚函数调用,从而消除了不需要该语言特性的真实虚函数调用的开销(时间和空间)。删除虚函数调用允许编译器提供更好的优化,从而获得更好的性能。
好处的清单一直在继续……不利的一面是,它在 C++ 中的语法很丑陋,但你学会了忍受它。使用宏来形成 mixin 链可以使代码更具可读性。
在我看来,我将 mixins 视为可用于构建类的可重用代码片段。通常,它们帮助您实现接口,提供通用的方法实现。你最终会觉得你可以“去购物”来购买构成你班级的部分,并且几乎不需要做任何“管道”来让这些部分协同工作。