本页面解释了 JavaScript 类设计中组合与继承的概念,以及何时优先选择其中一种方法。它为通过对对象关系做出适当的架构决策来编写可维护、灵活的代码提供了指导。
在面向对象编程中,建立类之间关系主要有两种方式:继承和组合。整洁代码原则“组合优于继承”指导开发人员在设计类关系时优先考虑组合,尽管继承在特定场景下仍然适用。
继承在类之间创建“是-A”关系。子类从父类继承属性和方法,并可以扩展或覆盖它们。
组合创建“拥有-A”关系。类不是继承,而是将其他类的实例作为属性包含在内,并委托给它们。
根据整洁代码指南,继承适用于以下特定场景:
在以下情况应优先考虑组合:
README 文件提供了一个明确的例子,说明组合优于继承
在此示例中,EmployeeTaxData 继承自 Employee,创建了一个不准确反映现实的“是-A”关系——税务数据不是员工的一种类型。
组合方法正确地建模了员工“拥有-A”税务数据组件的关系
| 方法 | 优点 | 缺点 |
|---|---|---|
| 继承 | - 清晰表示“是-A”关系 - 相关类之间的方法复用 - 对基类的更改会传播到所有派生类 | - 造成类之间的紧密耦合 - 当父类更改时易碎 - 在 JavaScript 中仅限于单继承 - 可能导致深层继承层次结构 |
| 组合 | - 更灵活、模块化的设计 - 更容易在运行时修改行为 - 更清晰的封装边界 - 组件间耦合度更低 | - 可能需要更多代码来委托操作 - 关系可能不如继承明显 - 可能需要额外的接口设计 |
在选择继承和组合时,请问自己以下问题:
如果关系是“拥有-A”或您需要灵活性,那么组合通常是更好的选择。
虽然继承是面向对象编程的强大特性,但组合通常能带来更灵活、更易于维护的代码。通过组合来建模关系,您可以创建更易于修改、扩展和测试的系统。请记住这个原则:“在可能的情况下,优先选择组合而非继承”,但请根据您的具体要求选择合适的方法。