是OOP&完全避免实现继承可能吗? [英] Is OOP & completely avoiding implementation inheritance possible?

查看:99
本文介绍了是OOP&完全避免实现继承可能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我会选择Java作为一个例子,大多数人都知道它,虽然其他所有OO语言都可以正常工作。

I will choose Java as an example, most people know it, though every other OO language was working as well.

Java和许多其他语言一样,都有接口继承和实现继承。例如。 Java类可以从另一个继承,并且每个在其中具有实现的方法(假设父级不是抽象的)也是继承的。这意味着接口是继承的,也是此方法的实现。我可以覆盖它,但我没有。如果我没有覆盖它,我继承了实现。

Java, like many other languages, has interface inheritance and implementation inheritance. E.g. a Java class can inherit from another one and every method that has an implementation there (assuming the parent is not abstract) is inherited, too. That means the interface is inherited and the implementation for this method as well. I can overwrite it, but I don't have to. If I don't overwrite it, I have inherited the implementation.

但是,我的类也可以继承(不是用Java术语)只是一个接口,没有实现。实际上接口实际上是用Java命名的,它们提供了接口继承,但没有继承任何实现,因为接口的所有方法都没有实现。

However, my class can also "inherit" (not in Java terms) just an interface, without implementation. Actually interfaces are really named that way in Java, they provide interface inheritance, but without inheriting any implementation, since all methods of an interface have no implementation.

现在有这个文章,说继承接口比实现更好,你可能想读它(至少在第一页的前半部分),这很有意思。它避免了脆弱的基类问题等问题。到目前为止,这一切都很有意义,文章中说的许多其他内容对我来说都很有意义。

Now there was this article, saying it's better to inherit interfaces than implementations, you may like to read it (at least the first half of the first page), it's pretty interesting. It avoids issues like the fragile base class problem. So far this makes all a lot of sense and many other things said in the article make a lot of sense to me.

对此我有什么不妥,是实现继承意味着代码重用,这是OO语言最重要的属性之一。现在如果Java没有类(比如James Gosling,Java的教父希望根据这篇文章),它解决了实现继承的所有问题,但是如何使代码重用成为可能?

What bugs me about this, is that implementation inheritance means code reuse, one of the most important properties of OO languages. Now if Java had no classes (like James Gosling, the godfather of Java has wished according to this article), it solves all problems of implementation inheritance, but how would you make code reuse possible then?

例如如果我有一个类Car和Car有一个方法move(),这会让Car移动。现在我可以为不同类型的汽车分类汽车,这些都是汽车,但都是汽车的专用版本。有些可能以不同的方式移动,这些都需要覆盖move(),但大多数只会保留继承的移动,因为它们像抽象的父Car一样移动。现在假设在Java中只有接口,只有接口可以相互继承,一个类可以实现接口,但所有类都是final,所以没有类可以从任何其他类继承。

E.g. if I have a class Car and Car has a method move(), which makes the Car move. Now I can sub-class Car for different type of cars, that are all cars, but are all specialized versions of Car. Some may move in a different way, these need to overwrite move() anyway, but most would simply keep the inherited move, as they move alike just like the abstract parent Car. Now assume for a second that there are only interfaces in Java, only interfaces may inherit from each other, a class may implement interfaces, but all classes are always final, so no class can inherit from any other class.

如果你有一个Interface Car和100个Car类,你需要为每个类实现相同的move()方法吗?在OO世界中存在除了实现继承之外的代码重用的哪些概念?

How would you avoid that when you have an Interface Car and hundred Car classes, that you need to implement an identical move() method for each of them? What concepts for code reuse other than implementation inheritance exist in the the OO world?

有些语言有Mixins。 Mixins是我问题的答案吗?我读到了它们,但我无法想象Mixins如何在Java世界中运行,以及它们是否真的可以在这里解决问题。

Some languages have Mixins. Are Mixins the answer to my question? I read about them, but I cannot really imagine how Mixins would work in a Java world and if they can really solve the problem here.

另一个想法是有一个只实现Car接口的类,我们称之为AbstractCar,并实现move()方法。现在其他汽车也实现了Car接口,在内部他们创建了一个AbstractCar实例,他们通过在内部抽象Car上调用move()来实现自己的move()方法。但这不会浪费资源(一种方法只调用另一种方法 - 好吧,JIT可以内联代码,但仍然)并使用额外的内存来保存内部对象,你甚至不需要实现继承? (毕竟每个对象需要更多的内存而不仅仅是封装数据的总和)对于程序员来说编写虚拟方法也不是很尴尬,例如

Another idea was that there is a class that only implements the Car interface, let's call it AbstractCar, and implements the move() method. Now other cars implement the Car interface as well, internally they create an instance of AbstractCar and they implement their own move() method by calling move() on their internal abstract Car. But wouldn't this be wasting resources for nothing (a method calling just another method - okay, JIT could inline the code, but still) and using extra memory for keeping internal objects, you wouldn't even need with implementation inheritance? (after all every object needs more memory than just the sum of the encapsulated data) Also isn't it awkward for a programmer to write dummy methods like

public void move() {
    abstractCarObject.move();
}

任何人都可以想象一个更好的想法如何避免实现继承,仍然能够以简单的方式重用代码?

Anyone can imagine a better idea how to avoid implementation inheritance and still be able to re-use code in an easy fashion?

推荐答案

简短的回答:是的,这是可能的。但你必须是故意这样做的,而不是偶然的(使用最终的,抽象的和带有继承的设计等)。

Short answer: Yes it is possible. But you have to do it on purpose and no by chance ( using final, abstract and design with inheritance in mind, etc. )

长答案:

好吧,继承实际上不是代码重用,而是用于专业化类,我认为这是一种误解。

Well, inheritance is not actually for "code re-use", it is for class "specialization", I think this is a misinterpretation.

例如,从Vector创建堆栈是一个非常糟糕的主意,因为它们是相似的。或者来自HashTable的属性只是因为它们存储了值。参见[有效]。

For instance is it a very bad idea to create a Stack from a Vector, just because they are alike. Or properties from HashTable just because they store values. See [Effective].

代码重用更像是OO特征的业务视图,这意味着您的对象可以在节点之间轻松分发;并且是可移植的,并且没有以前编程语言生成的问题。事实已证明这一点很严重。我们现在拥有可以轻松分发的库;例如,在java中,jar文件可以在任何项目中使用,从而节省数千小时的开发时间。 OO仍有一些可移植性和类似的问题,这就是现在WebServices如此受欢迎的原因(就像之前的CORBA一样),但那是另一个主题。

The "code reuse" was more a "business view" of the OO characteristics, meaning that you objects were easily distributable among nodes; and were portable and didn't not have the problems of previous programming languages generation. This has been proved half rigth. We now have libraries that can be easily distributed; for instance in java the jar files can be used in any project saving thousands of hours of development. OO still has some problems with portability and things like that, that is the reason now WebServices are so popular ( as before it was CORBA ) but that's another thread.

这是代码重用的一个方面。另一个是有效的,与编程有关的那个。但在这种情况下,不仅仅是保存代码行并创建脆弱的怪物,而是考虑到继承的设计。这是前面提到的书中的第17项; 第17项:继承的设计和文件,或禁止它。参见[有效]

This is one aspect of "code reuse". The other is effectively, the one that has to do with programming. But in this case is not just to "save" lines of code and creating fragile monsters, but designing with inheritance in mind. This is the item 17 in the book previously mentioned; Item 17: Design and document for inheritance or else prohibit it. See [Effective]

当然,你可能有一个Car类和吨子类。是的,你提到的关于Car interface,AbstractCar和CarImplementation的方法是正确的方法。

Of course you may have a Car class and tons of subclasses. And yes, the approach you mention about Car interface, AbstractCar and CarImplementation is a correct way to go.

你定义了汽车应该遵守的合同,并说这些是我在谈论汽车时所期望的方法。具有基本功能的抽象汽车,每辆汽车都离开并记录子类负责处理的方法。在java中,你通过将方法标记为抽象来实现这一点。

You define the "contract" the Car should adhere and say these are the methods I would expect to have when talking about cars. The abstract car that has the base functionality that every car but leaving and documenting the methods the subclasses are responsible to handle. In java you do this by marking the method as abstract.

当你以这种方式进行时,脆弱类(或者至少是设计者)没有问题是有意识的还是威胁的)子类只完成设计者允许的那些部分。

When you proceed this way, there is not a problem with the "fragile" class ( or at least the designer is conscious or the threat ) and the subclasses do complete only those parts the designer allow them.

继承更多的是专门化类,以同样的方式卡车是Car的专用版本,MosterTruck是Truck的专用版本。

Inheritance is more to "specialize" the classes, in the same fashion a Truck is an specialized version of Car, and MosterTruck an specialized version of Truck.

它不会因为它有一个来自汽车而创建一个ComputerMouse亚类酶轮子(滚轮)就像汽车一样,它会移动,下面有一个轮子,只是为了节省代码行。它属于不同的域,它将用于其他目的。

It does not make sanse to create a "ComputerMouse" subclase from a Car just because it has a Wheel ( scroll wheel ) like a car, it moves, and has a wheel below just to save lines of code. It belongs to a different domain, and it will be used for other purposes.

防止实现继承的方法是从编程语言开始,你应该在类声明中使用final关键字,这样就禁止了子类。

The way to prevent "implementation" inheritance is in the programming language since the beginning, you should use the final keyword on the class declaration and this way you are prohibiting subclasses.

如果有意的话,子类化并不是邪恶的。如果做得不好,可能会成为一场噩梦。我会说你应该尽可能私密和最终开始,如果需要的话,可以让事情变得更加公开和可扩展。这也在演示文稿如何设计好的API及其重要性中进行了广泛的解释。参见[Good API]

Subclassing is not evil if it's done on purpose. If it's done uncarefully it may become a nightmare. I would say that you should start as private and "final" as possible and if needed make things more public and extend-able. This is also widely explained in the presentation"How to design good API's and why it matters" See [Good API]

继续阅读文章并及时和实践(和很多耐心)这件事情会更加清晰。虽然有时您只需要完成工作并复制/粘贴一些代码:P。这是好的,只要你尝试先做好。

Keep reading articles and with time and practice ( and a lot of patience ) this thing will come clearer. Although sometime you just need to do the work and copy/paste some code :P . This is ok, as long you try to do it well first.

以下是来自Joshua Bloch的参考资料(以前在Sun工作的Java核心工作谷歌)



[有效]
有效的Java。绝对是非初学者应该学习,理解和实践的最好的Java书。必须有。

Here are the references both from Joshua Bloch ( formerly working in Sun at the core of java now working for Google )


[Effective] Effective Java. Definitely the best java book a non beginner should learn, understand and practice. A must have.

Effective Java



[Good API]介绍API的设计,可重用性和相关主题。
它有点冗长但值得每分钟。


[Good API]Presentation that talks on API's design, reusability and related topics. It is a little lengthy but it worth every minute.

如何设计一个好的API及其原因它很重要

问候。



更新:看一看在我发给你的视频链接的第42分钟。它讨论了这个主题:


Update: Take a look at minute 42 of the video link I sent you. It talks about this topic:

如果你在公共API中有两个类,并且你想让一个类成为另一个的子类,就像Foo是Bar的子类,问问你自己,Every Foo是吧?...

"When you have two classes in a public API and you think to make one a subclass of another, like Foo is a subclass of Bar, ask your self , is Every Foo a Bar?... "

在谈论TimeTask时,它在前一分钟讨论了代码重用。

And in the minute previous it talks about "code reuse" while talking about TimeTask.

这篇关于是OOP&完全避免实现继承可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆