我听说组合比继承更好。因此,当我设计简单的游戏引擎时,我倾向于执行以下操作:
而不是:
这是一个好方法,还是我应该重新考虑?
修改:澄清符号。箭头表示继承,带有菱形的箭头表示组成,<>>。是指界面。有关符号的更多信息,请访问yUML webpage。
答案 0 :(得分:4)
好的,这里有几件事要介绍。
首先:为什么需要表达PointLight
和Spotlight
之间的共性?是吗
Light
,并且不关心它们的种类?因为客户需要统一处理灯光
这是接口继承,也称为子类型。作文在这里不适用 - 因为没有什么可以写的。您可以通过两种方式实现这一点:您选择的方式在很大程度上取决于您的语言。
ILight
)来实现。客户端只依赖于接口,而不是它的实现。每个PointLight
和SpotLight
都会实现界面。PointLight
和SpotLight
的抽象基类。因为您想分享实施
通常有两种方法可以实现这一目标:
Light
并在其中实现常见行为。将PointLight
和SpotLight
声明为继承自Light
,根据需要覆盖/添加行为。PointLight
和SpotLight
,而不继承公共超类。实现实现常见行为的第三个类(您可能仍然可以调用Light
)。 PointLight
和SpotLight
都包含一个'Light`实例,并为其共享行为委托。对于您的具体示例,在Implementation inheritance和Composition之间选择相对较少。当继承层次结构变得更深时,会出现前者的问题。在支持多实现继承的语言(例如脆弱的基类问题)中,这也是出了名的错误。另一方面,实现继承意味着更少的输入:语言自动委托给共享行为,而使用Composition,你需要编写委托方法。
<强>摘要强>
另请注意,上述内容并非相互排斥:您可以,例如:
ILight
和SpotLight
实施的接口PointLight
从根本上说,你需要清楚自己想要达到的目标。
第h
答案 1 :(得分:1)
我认为你应该看一下基于组件的设计。看看this,最佳答案有一些很好的资源。
答案 2 :(得分:0)
我认为你不应该根据某种谣言作出决定。有时组合非常好,但它需要更多代码编写并且更难以支持(如果更改BasicLight接口,则应手动更改所有依赖类)。继承解决了这个问题和其他一些问题。 在某些情况下,组合是可取的,但它们主要出现在复杂的项目中。