当有现有类时,接口如何取代多重继承的需要

首先。。。很抱歉这篇文章。我知道有很多很多关于stackoverflow的帖子都在讨论多重继承。但是我已经知道Java不支持多重继承,我知道使用接口应该是一种替代方案。但我不明白,看到我的困境:

我必须对一个用Java编写的非常非常大且复杂的工具进行更改。在此工具中,有一个数据结构,其中包含许多具有链接成员层次结构的不同类对象。无论如何。。。

  • 我有一个类,它有多个方法,并根据对象的类返回一个对象标签。它需要成员和静态变量。Tagged
  • 第二个类允许链接对象,并最终生成一个XML文件。我还需要成员和静态变量。XMLElement
  • 最后,我有这么多数据类,它们几乎都应该扩展,其中一些。XMLElementTagged

好吧,好吧,这不起作用,因为它只能扩展一个类。我经常读到,Java的一切都是可以的,不需要多重继承。我相信,但我不明白接口应该如何取代继承。

  1. 将实际实现放在所有数据类中是没有意义的,因为它每次都是相同的,但这对于接口是必要的(我认为)。
  2. 我不明白如何将我的一个继承类更改为接口。我在这里有变量,它们必须正好在那里。

我真的不明白,所以请有人可以解释一下我如何处理这个问题?


答案 1

实际上,除了Java应该具有多重继承之外,我没有很好的答案。接口应该能够取代对多重继承的需求,就像一个大谎言,当重复足够多的次数时,就会变成真的。

争论是多重继承导致了所有这些问题(la-di-dah),但我不断听到那些从未使用过C++Java开发人员的论点。我也不记得C++程序员说过“哎呀,我喜欢C++,但如果他们只摆脱多重继承,它就会成为一门很棒的语言”。人们在实用时使用它,当它不实用时不使用它。

您的问题是多重继承合适的经典案例。任何重构代码的建议实际上都在告诉你如何解决Java没有多重继承的问题。

此外,所有关于“哦,代表团更好,la-di-dah”的讨论都混淆了宗教与设计。没有正确的方法。事情要么更有用,要么更无用,仅此而已。

在你的情况下,多重继承将更有用,更优雅的解决方案。

至于将你的代码重构成一种不太有用的形式,以满足所有从未使用过多重继承并相信“多重继承是坏的”的宗教人士,我想你将不得不降级你的代码,因为我不认为Java在短期内以这种方式“改进”。有太多的人重复宗教咒语,以至于愚蠢到我看不到它被添加到语言中。

实际上,我为你提供的解决方案是“x extends Tagged, XMLElement”,仅此而已。

...但是,从上面提供的解决方案中可以看出,大多数人认为这样的解决方案太复杂和令人困惑!

我宁愿自己冒险进入“x扩展a,b”的领域,即使这是一个非常可怕的解决方案,可能会压倒大多数Java程序员的能力。

上面提出的解决方案更令人惊讶的是,在座的每个人都建议你把你的代码重构为“委托”,因为多重继承是坏的,如果他们遇到同样的问题,就会通过简单地解决问题:“x扩展a,b”并完成它,他们所有关于“授权与继承”的宗教争论都会消失。整个辩论是愚蠢的,只有无知的程序员才能提出,他们只能证明他们能从一本书中背诵得有多好,以及他们自己思考的有多少。

你是100%正确的,多重继承会有所帮助,不,如果你认为Java应该有它,那么你在你的代码中做了任何错误。


答案 2

您可能应该更喜欢组合(和委派)而不是继承:

public interface TaggedInterface {
    void foo();
}

public interface XMLElementInterface {
    void bar();
}

public class Tagged implements TaggedInterface {
    // ...
}

public class XMLElement implements XMLElementInterface {
    // ...
}

public class TaggedXmlElement implements TaggedInterface, XMLElementInterface {
    private TaggedInterface tagged;
    private XMLElementInterface xmlElement;

    public TaggedXmlElement(TaggedInterface tagged, XMLElementInterface xmlElement) {
        this.tagged = tagged;
        this.xmlElement = xmlElement;
    }

    public void foo() {
        this.tagged.foo();
    }

    public void bar() {
        this.xmlElement.bar();
    }

    public static void main(String[] args) {
        TaggedXmlElement t = new TaggedXmlElement(new Tagged(), new XMLElement());
        t.foo();
        t.bar();
    }
}

推荐