有没有什么组合不能完成继承可以做到的? [英] Is there anything composition cannot accomplish that inheritance can?

查看:17
本文介绍了有没有什么组合不能完成继承可以做到的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

组合和继承.

我知道它们都是在适当的时候选择的工具,在组合和继承之间进行选择时,上下文非常重要.然而,关于每个人的适当背景的讨论通常有点模糊.这让我开始考虑继承和多态是传统 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 将在控制台中打印 "A B".

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() ; ... }
}

我们需要在 B 中定义 printName 并在 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 具有委托的内置功能(您可以阅读这里继承如何在 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 中的 equality 也可能存在一些问题并且 equals 如果使用继承.但另一方面,它仍然是解决一些问题的一种非常优雅的方式.

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.

(我的理论是,当有人开始做面向对象时,我们倾向于过度使用继承,因为它被认为是语言的特性.然后我们学习委托,即模式/方法,我们也学会喜欢它.一段时间后,我们在两者之间找到平衡,并培养直觉,在哪种情况下哪个更好.好吧,如您所见,我仍然喜欢两者,两者都值得谨慎考虑正在介绍.)

(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天全站免登陆