OOP和完全避免实现继承是可能的吗?
我将选择Java作为一个例子,大多数人都知道它,尽管其他所有OO语言也在工作。
与许多其他语言一样,Java具有接口继承和实现继承。例如,一个Java类可以从另一个类继承,并且每个具有实现的方法(假设父级不是抽象的)也是继承的。这意味着接口是继承的,也是此方法的实现。我可以覆盖它,但我不必这样做。如果我不覆盖它,我就继承了实现。
但是,我的类也可以“继承”(不是Java术语)只是一个接口,而无需实现。实际上,接口在Java中实际上是以这种方式命名的,它们提供接口继承,但不继承任何实现,因为接口的所有方法都没有实现。
现在有这篇文章,说继承接口比实现更好,你可能喜欢阅读它(至少是第一页的前半部分),这很有趣。它避免了像脆弱的基类问题这样的问题。到目前为止,这一切都很有意义,文章中说的许多其他事情对我来说也很有意义。
让我烦恼的是,实现继承意味着代码重用,这是OO语言最重要的属性之一。现在,如果Java没有类(就像Java教父James Gosling根据本文所希望的那样),它可以解决实现继承的所有问题,但是您将如何使代码重用成为可能呢?
例如,如果我有一个类 Car,而 Car 有一个 move() 方法,这使得 Car 移动。现在我可以将Car归类为不同类型的汽车,这些都是汽车,但都是汽车的专用版本。有些可能以不同的方式移动,无论如何,这些都需要覆盖move(),但大多数会简单地保留继承的移动,因为它们的移动方式与抽象的父Car相同。现在假设Java中只有接口,只有接口可以相互继承,类可以实现接口,但所有类始终是最终的,因此任何类都不能从任何其他类继承。
当你有一个 Interface Car 和一百个 Car 类时,你如何避免需要为每个类实现一个相同的 move() 方法?除了实现继承之外,OO世界中还存在哪些代码重用概念?
有些语言有Mixins。Mixins是我问题的答案吗?我读过关于它们的文章,但我无法想象Mixins在Java世界中将如何工作,以及它们是否真的能在这里解决问题。
另一个想法是,有一个类只实现Car接口,我们称之为抽象Car,并实现move()方法。现在其他汽车也实现了Car接口,它们在内部创建了一个抽象Car的实例,并通过在其内部抽象Car上调用move()来实现自己的move()方法。但是,这难道不是在浪费资源(一个方法只调用另一个方法 - 好吧,JIT可以内联代码,但仍然)并使用额外的内存来保留内部对象,你甚至不需要实现继承?(毕竟每个对象需要更多的内存,而不仅仅是封装数据的总和)对于程序员来说,编写像这样虚拟的方法也不是很尴尬吗?
public void move() {
abstractCarObject.move();
}
?
任何人都可以想象一个更好的想法,如何避免实现继承,并且仍然能够以简单的方式重用代码?