Kap*_*old 60 java language-agnostic oop inheritance composition
我知道之前已经讨论过这个问题,但似乎总是假设继承至少有时候比组合更好.我想挑战这个假设,希望获得一些理解.
我的问题是:既然你可以完成与对象组合东西,你可以用经典的继承和自经典的继承是很经常被滥用[1] ,自对象组合为您提供了灵活地改变委托对象运行时,为什么你会永远使用经典继承?
我可以理解为什么你会推荐Java和C++等语言中的继承,这些语言不能提供方便的委派语法.在这些语言中,只要不明显不正确,就可以使用继承来节省大量的输入.但是像Objective C和Ruby这样的其他语言提供了经典的继承和非常方便的委托语法.Go编程语言是我所知道的唯一一种语言,它认为经典继承比它的价值更麻烦,并且仅支持代码重用的委托.
陈述我的问题的另一种方式是:即使您知道经典继承对于实现某个模型不是不正确的,那么这个理由是否足以使用它而不是组合?
[1]许多人使用经典继承来实现多态,而不是让他们的类实现接口.继承的目的是代码重用,而不是多态.此外,有些人使用继承来模拟他们对"is-a"关系的直观理解,这种关系往往是有问题的.
更新
我只想在谈到继承时澄清我的意思:
我在谈论一种继承的类型,即一个类继承自部分或完全实现的基类.我不是在谈论继承纯粹抽象的基类,这与实现接口相同,我记录的并不反对.
更新2
我知道继承是实现C++多态性的唯一方法.在这种情况下,显而易见的是你必须使用它.所以我的问题仅限于Java或Ruby等语言,这些语言提供了实现多态的不同方法(分别是接口和鸭子类型).
Jer*_*fin 49
继承的目的是代码重用,而不是多态.
这是你的根本错误.几乎完全恰恰相反.(公共)继承的主要目的是建模相关类之间的关系.多态性是其中很大一部分.
如果使用正确,继承不是重用现有代码.相反,它是由现有代码使用.也就是说,如果您现有的代码可以使用现有的基类,那么当您从该现有基类派生一个新类时,其他代码现在也可以自动使用您的新派生类.
可以使用继承来重用代码,但是当/如果这样做,它通常应该是私有继承而不是公共继承.如果您使用的语言支持委派,那么您很少有充分的理由使用私有继承.OTOH,私有继承确实支持委托(通常)没有的一些事情.特别是,即使多态性是在这种情况下,一个决定性的次要问题,它可能仍然是一个问题-即与私有继承,你可以从一个基类,我们开始几乎你想要什么,并且(假设它允许)覆盖部分不太正确.
使用委托,您唯一真正的选择是完全按照现有的类使用它.如果它没有达到您想要的效果,那么您唯一真正的选择就是完全忽略该功能,并从头开始重新实现它.在某些情况下,这并没有损失,但在其他情况下则相当可观.如果基类的其他部分使用多态函数,则私有继承允许您仅覆盖多态函数,其他部分将使用重写函数.使用委派,您无法轻松插入新功能,因此现有基类的其他部分将使用您已覆盖的内容.
小智 16
使用继承的主要原因不是作为一种组合形式 - 它可以让你获得多态行为.如果你不需要多态,你可能不应该使用继承,至少在C++中.
dsi*_*cha 12
如果您将未显式覆盖的所有内容委托给实现相同接口的其他对象("基础"对象),那么您基本上在组合的基础上进行Greenspunned继承,但(在大多数语言中)具有更多详细程度和样板.使用组合而不是继承的目的是,您只能委派要委派的行为.
如果您希望对象使用基类的所有行为,除非显式重写,那么继承是表达它的最简单,最简单,最直接的方式.
每个人都知道多态性是继承的一大优势.我在继承中发现的另一个好处是有助于创建现实世界的复制品.例如,在付费滚动系统中,如果我们使用超类Employee继承所有这些类,我们会处理经理开发人员,办公室男生等.它使我们的程序在现实世界的背景下更容易理解,所有这些类基本上都是员工.还有一个类不仅包含它们还包含属性的方法.因此,如果我们在Employee类中包含通用于员工的属性,如社会安全号码年龄等,它将提供更多的代码重用和概念清晰度,当然还有多态性.然而,在使用继承的东西时,我们应该牢记基本的设计原则"
如果符合以下情况,则首选继承:
我的结论:委托是一种编程语言中的错误的解决方法.