是否有任何组合无法实现继承可以? [英] Is there anything composition cannot accomplish that inheritance can?

查看:147
本文介绍了是否有任何组合无法实现继承可以?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

组合和继承。

我知道它们都是适当时选择的工具,上下文在组合和继承之间进行选择时非常重要。然而,关于每个的适当背景的讨论通常有点模糊;这让我开始考虑传统OOP的独特方面是多么明显的继承和多态。

I am aware that they are both tools to be chosen when appropriate, and context is very important in choosing between composition and inheritance. However, the discussion about the appropriate context for each is usually a little fuzzy; this has me beginning to consider just how distinctly inheritance and polymorphism are separate aspects of traditional OOP.

多态性允许人们同等地指定is-a关系以及继承。特别是,从基类继承隐式地创建该类与其子类之间的多态关系。然而,尽管可以使用纯接口实现多态,但是继承通过同时传输实现细节使多态关系复杂化。通过这种方式,继承与纯多态性完全不同。

Polymorphism allows one to specify "is-a" relationships equally as well as inheritance. Particularly, inheriting from a base class implicitly creates a polymorphic relationship between that class and its subclasses. However, whereas polymorphism can be implemented using pure interfaces, inheritance complicates the polymorphic relationship by simultaneously transferring implementation details. In this way, inheritance is quite distinct from pure polymorphism.

作为一种工具,继承通过简化实现重用来为程序员提供与多态(通过纯接口)不同的方式 在琐碎的情况下 。但是,在大多数情况下,超类的实现细节与子类的要求略有冲突。这就是为什么我们有覆盖和成员隐藏的原因。在这些情况下,继承所提供的实现重用是通过在级联级别的代码中验证状态更改和执行路径的额外工作来购买的:子类的完整扁平化实现细节分布在多个类之间,这通常意味着多个文件,其中只有部分适用于相关的子类。在处理继承时,查看该层次结构是绝对必要的,因为如果不查看超类的代码,就无法知道哪些未覆盖的详细信息会对您的状态进行整理或转移您的执行。

As a tool, inheritance serves programmers differently than polymorphism (through pure interfaces) by simplifying implementation re-use in trivial cases. In the majority of cases, however, the implementation details of a superclass subtly conflict with the requirements of a subclass. This is why we have "overrides" and "member hiding". In these cases, the implementation re-use offered by inheritance is purchased with the added effort of verifying state changes and execution paths across cascading levels of code: the complete "flattened" implementation details of the subclass are spread between multiple classes, which usually means multiple files, of which only portions apply to the subclass in question. Looking through that hierarchy is absolutely necessary when dealing with inheritance, because without looking at the code of the superclass, there is no way to know what un-overidden details are monkeying with your state or diverting your execution.

相比之下,独占使用组合保证您将看到可以通过显式实例化对象修改哪些状态,其对象的方法可由您自行调用。真正扁平化的实现仍然没有实现(实际上甚至不可取,因为结构化编程的好处是实现细节的封装和抽象)但是你仍然可以重用代码,你只需要在一个地方查看当代码行为不端时。

In comparison, exclusive use of composition guarantees you will see what state can be modified by explicitly instantiated objects whose methods are invoked at your discretion. Truly flattened implementation is still not achieved (and actually isn't even desirable, since the benefit of structured programming is the encapsulation and abstraction of implementation details) but you still get your code-reuse, and you will only have to look in one place when the code misbehaves.

为了在实践中测试这些想法,避免传统继承为基于纯接口的多态性和对象组合的组合,我想知道,

With the goal of testing these ideas in practice, eschewing traditional inheritance for a combination of pure interface-based polymorphism and object composition, I am wondering,

有什么对象组合和接口无法实现继承吗?

Is there anything object composition and interfaces cannot accomplish that inheritance can?

编辑

在迄今为止的回复中,ewernli认为,没有技术专长可用于一种技术而不能用于另一种技术;后来他提到了每种技术固有的不同模式和设计方法。这是有道理的。但是,这个建议让我通过询问是否专用组合和界面代替传统继承会禁止使用任何主要设计模式来改进我的问题?如果是这样,在我的情况下是不是有相同的模式?

In the responses so far, ewernli believes there are no technical feats available for one technique but not the other; he later mentions how different patterns and design approaches are inherent to each technique. This stands to reason. However, the suggestion leads me to refine my question by asking whether exclusive use of composition and interfaces in lieu of traditional inheritance would prohibit the use of any major design patterns? And if so, aren't there equivalent patterns for use in my situation?

推荐答案

从技术上讲,通过继承可以实现的一切都可以也可以通过授权来实现。所以答案是不。

Technically everything that can be realized with inheritance can be realized with delegation as well. So the answer would be "no".

将继承转换为委派

假设我们实现了以下类继承:

Let's say we have the following classes implemented with inheritance:

public class A {
    String a = "A";
    void doSomething() { .... }
    void getDisplayName() {  return a }
    void printName { System.out.println( this.getDisplayName() };   
}

public class B extends A {
    String b = "B";
    void getDisplayName() {  return a + " " + b; }
    void doSomething() { super.doSomething() ; ... }    
}

这些东西有效很好,并且在B的实例上调用 printName 将在控制台中打印AB

The stuff works nicely, and calling printName on an instance of B will print "A B" in the console.

现在,如果我们用委托重写,我们得到:

Now, if we rewrite that with delegation, we get:

public class A {
    String a = "A";
    void doSomething() { .... }
    void getDisplayName() {  return a }
    void printName { System.out.println( this.getName() };  
}

public class B  {
    String b = "B";
    A delegate = new A();
    void getDisplayName() {  return delegate.a + " " + b; }
    void doSomething() { delegate.doSomething() ; ... } 
    void printName() { delegate.printName() ; ... }
}

我们需要定义 printName < B中的/ code>以及在实例化B时创建委托。对 doSomething 的调用将以与继承类似的方式工作。但是对 printName 的调用将在控制台中打印A。确实有了委托,我们失去了强大的this概念被绑定到对象实例,而基本方法能够调用已被覆盖的方法。

We need to define printName in B and also to create the delegate when B is instantiated. A call to doSomething will work in a similar way as with inheritance. But a call to printName will print "A" in the console. Indeed with delegation, we lost the powerful concept of "this" being bound to the object instance and base methods being able to call methods that have be override.

这可以用支持纯委托的语言来解决。使用纯委托,委托中的this仍将引用B的实例。这意味着 this.getName()将从B类启动方法分派。我们实现与继承相同。这是基于原型语言中使用的机制,例如具有委托功能的自我具有内置功能(您可以阅读这里继承如何在Self中工作)。

This can be solved in the language supports pure delegation. With pure delegation, "this" in the delegate will still reference the instance of B. Which means that this.getName() will starts the method dispatch from class B. We achieve the the same as with inheritance. This is the mechanism used in prototype-based language such as Self which have delegation has a built-in feature (You can read here how inheritance works in Self).

但Java没有纯委托。什么时候被卡住了?不,我们仍然可以通过更多的努力来做到这一点:

But Java doesn't have pure delegation. Are when then stuck? No really, we can still do that ourselves with some more effort:

public class A implements AInterface {
    String a = "A";
    AInterface owner; // replace "this"
    A ( AInterface o ) { owner = o }
    void doSomething() { .... }
    void getDisplayName() {  return a }
    void printName { System.out.println( owner.getName() }; 
}

public class B  implements AInterface {
    String b = "B";
    A delegate = new A( this );
    void getDisplayName() {  return delegate.a + " " + b; }
    void doSomething() { delegate.doSomething() ; ... } 
    void printName() { delegate.printName() ; ... }
}

我们基本上重新实现内置继承所提供的内容。它是否有意义?不是真的。但它说明继承总是可以转换为委托。

We are basically re-implementing what the built-in inheritance provides. Does it make sense? No really. But it illustrates that inheritance can always be converted to delegation.

讨论

继承的特点是基类可以调用在子类中重写的方法。例如模板模式。这种事情不能通过授权轻松完成。另一方面,这正是使继承难以使用的原因。它需要精神上的扭曲来理解多态分派发生的位置以及如果覆盖方法会产生什么影响。

Inheritance is characterized by the fact that a base class can call a method that is overridden in a sub class. This is for instance the essence of the template pattern. Such things can not be done easily with delegation. On the other hand, this is exactly what makes inheritance hard to use. It require a mental twist to understand where polymorphic dispatch happen and what is the effect if methods are overridden.

关于继承以及它可能在设计中引入的脆弱性,有一些已知的缺陷。特别是如果类层次结构发展。 平等中的 hashCode <也可能存在一些问题/ code>和等于如果使用继承。但另一方面,解决一些问题仍然是一种非常优雅的方式。

There are some known pitfalls about inheritance and the fragility it may introduce in the design. Especially if the class hierarchy evolves. There can also be some issues with equality in hashCode and equals if inheritance is used. But on the other side, it's still a very elegant way to solve some problems.

此外,即使继承可以用委托代替,你也可以说它们仍然存在实现不同的目的并相互补充 - 它们没有传达相同的意图,而这些意图没有被纯粹的技术等价所捕获。

Also, even if inheritance can be replaced with delegation, one you can argue that they still achieve different purpose and complement each other -- they don't convey the same intention which is not captured by pure technical equivalence.

(我的理论是,当有人开始做OO时,我们很想过度使用继承,因为它被认为是语言的特征。然后我们学习授权,即模式/方法我们也学会喜欢它。经过一段时间后,我们找到两者之间的平衡和直觉感的发展,在这种情况下哪一个更好。嗯,正如你所看到的,我仍然喜欢两者,两者都值得一些在介绍之前要小心。)

(My theory is that when somebody starts doing OO, we are tempted to over-use inheritance because it's perceive like a feature of the language. Then we learn delegation which is pattern/approach and we learn to like it as well. After some time, we find a balance between both and develop of sense of intuition of which one is better in which case. Well, as you can see, I still like both, and both deserve some caution before being introduced.)

一些文献


继承和委托是
备用方法增量
定义和共享。它有
,一般认为委托
提供了更强大的模型。这篇
的论文证明了有一个
自然继承模型,
捕获
委托的所有属性。独立地,
授权捕获继承的能力的某些
限制是
。最后,概述了一个新的框架
,它完全捕获了委托
和继承,并且探索了这个混合
模型的一些
的分支。

Inheritance and delegation are alternate methods for incremental definition and sharing. It has commonly been believed that delegation provides a more powerful model. This paper demonstrates that there is a "natural" model of inheritance which captures all of the properties of delegation. Independently, certain constraints on the ability of delegation to capture inheritance are demonstrated. Finally, a new framework which fully captures both delegation and inheritance is outlined, and some of the ramifications of this hybrid model are explored.




  • 关于继承的概念


  • 其中一个最有趣的 - 在
    同时,
    面向对象编程中最有问题的概念是
    继承。继承通常是
    被视为
    将面向对象的
    编程与其他现代
    编程范例区分开来的特性,但研究人员
    很少就其含义和用法达成一致。 [...]

    One of the most intriguing—and at the same time most problematic—notions in object-oriented programing is inheritance. Inheritance is commonly regarded as the feature that distinguishes object-oriented programming from other modern programming paradigms, but researchers rarely agree on its meaning and usage. [...]




    • 系统地重构java中的委托继承


    • 由于类的强耦合和不需要的类成员的扩散通过继承引起
      ,因此使用组合和委托的建议已经变得司空见惯。
      文献中相应重构的表述可能导致人们相信
      这样的转换是一项直接的任务。 [...]

      Because of the strong coupling of classes and the proliferation of unneeded class members induced by inheritance, the suggestion to use composition and delegation instead has become commonplace. The presentation of a corresponding refactoring in the literature may lead one to believe that such a transformation is a straightforward undertaking. [...]

      这篇关于是否有任何组合无法实现继承可以?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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