![](/img/trans.png)
[英]Best way to maximize code reuse while avoiding implementation inheritance and maintaining internalization
[英]Best way to apply inheritance and code reuse
在基类中的某些方法在继承类中没有意义的情况下,我有一个关于构建代码以使用继承重用的最佳方法的问题。 我认为这是一个普遍的 OOP 问题,而不仅仅是 TypeScript 的特有问题......
所以基本上,在某种形式的伪代码中,问题类似于:
类 BaseClass 使SenseForA 使SsenseForA .... doesnotMakeSenseForA doesnotMakeSenseForA ....
那么如何让Class A
继承BaseClass
。 只是直接继承意味着Class A
将具有没有真正意义的成员方法。
不使用继承意味着代码会在BaseClass
和Class A
重复
将makesSenseForA
方法移动到一个外部类并且让BaseClass
和它的子类都依赖于这个提取的类(即使用组合)在这个特定场景中不起作用,因为提取的类实际上应该被视为A BaseClass
。
处理这种 OOP 建模情况的最佳方法到底是什么?
编辑:由于缺乏更好的例子,这就像试图模拟Human
和Cyborg
- 这两个将共享大量类似的实现,因此首先想到的可能是让Cyborg
扩展Human
......
但也会有大量的实现, Human
拥有而Cyborg
不应该拥有的。
取消继承意味着必须在Human
和 Cyborg 中复制那些类似的功能。
并且组合也不起作用,因为如果您将那些相似的实现提取到一个单独的对象中,该对象及其方法将具有Human
属性,因此在我们的建模中应该被视为一个Human
。
是的,这确实是一个普遍的问题。 但是您的示例并不是对继承的非常准确的引用。 我们主要使用继承而不是因为公共功能。 为了重用它们,公共函数可以编写为实用程序/实用程序类。 当一个类基本上是父类的子类型时,您会继承它,并且我们为不是实际对象而是类型的事物创建接口。 例如:
注意, Animal
本身不能被客观化。 现在,即使Goat
和Tiger
两个类的许多功能都是通用的,但两者都不应该扩展另一个,因为hunt()
方法对 Goat 类没有意义,而graze()
对 Goat 类没有意义Tiger
。 为此,我们使用接口。 现在,要在同一个类中移动通用函数,您可以进一步打破这种模块化:
猜测Goat
和Tiger
现在将实施什么没有布朗尼积分。 万一有一些常见的函数,由于某种原因你不能写在Animal
类中,你可以把它们写成一个实用程序。 假设您有一只机器山羊,它具有许多与实际山羊相同的通用功能,您不extend Goat
,而是将通用功能作为实用程序移动,例如GoatUtilities
。
编辑:有人指出实用程序类不完全是面向对象编程,而是程序化的......但它们绝对可以赞美您的类,以帮助他们以正确的方式遵循面向对象编程。 这就是为什么它们是“实用程序”类。 所以,这是被遗漏的一点,我试图指出的基本上是在给定的例子中继承是如何被误解/误用的,这在某种程度上导致了有点违反 OOP 原则的问题。 拥有可行的面向对象设计并不意味着您不应该使用实用程序类,因为目标是应用继承和代码重用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.