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

fpd*_*gon 54 java inheritance interface multiple-inheritance

首先......对不起这篇文章.我知道stackoverflow上有很多帖子正在讨论多重继承.但我已经知道Java不支持多重继承,我知道使用接口应该是另一种选择.但我不明白并看到我的困境:

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

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

好的,这不会起作用,因为它只能扩展一个类.我经常读到Java的所有内容都没问题,也没有必要进行多重继承.我相信,但我不知道接口应如何取代继承.

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

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

小智 74

实际上,除了Java应该有多重继承之外,我没有其他好的答案.接口应该能够取代多重继承的要点就像是重复足够多次成为现实的大谎言.

参数是多重继承导致所有这些问题(la-di-dah),但我一直听到那些从未使用过C++的Java开发人员的论点.我也不记得C++程序员说"哎呀,我喜欢C++,但如果他们只能摆脱多重继承,它就会变成一种很棒的语言".人们在实际时使用它而不是在实际时使用它.

您的问题是多重继承适用的经典案例.任何重构代码的建议都告诉你如何解决Java没有多重继承的问题.

所有关于"哦,代表团更好,拉迪达"的讨论都让宗教与设计混淆.没有正确的方法.事情要么更有用,要么不那么有用.

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

至于重构你的代码到一个不太有用的形式,以满足所有从未使用过多重继承的宗教人士,并相信"多重继承是坏的",我想你将不得不降级你的代码,因为我没有看到Java"改进"很快就会这样.有太多人重复宗教咒语到愚蠢的程度,我无法看到它被添加到语言中.

实际上,我的解决方案是"x extends Tagged,XMLElement",这就是全部.

......但正如您从上面提供的解决方案中可以看到的,大多数人认为这样的解决方案将是复杂和混乱的方式!

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

上面建议的解决方案更令人惊讶的是,这里的每个人都建议你将代码重构为"委托",因为多重继承很糟糕,如果他们遇到同样的问题,就会通过简单地解决问题来解决问题:"x扩展a,b"并完成它,所有关于"委托与继承"的宗教论点都将消失.整个辩论都是愚蠢的,只有无知的程序员才能提出这个问题,他们只能证明他们能够从书中背诵出来的程度以及他们对自己的思考能力如何.

100%正确,多重继承会有所帮助,不,如果你认为Java应该拥有它,你在代码中做错了什么.

  • 这应该是最好的答案:) (3认同)
  • 阿门!血腥的c#和.net人都是如此.Bertrand Meyer曾经说过.net和java没有多重继承的唯一原因是难以编写支持多个基类的类加载器. (3认同)

JB *_*zet 57

你应该赞成组合(和委托)而不是继承:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我可以问一个愚蠢的问题吗?上面`TaggedXmlElement`类的构造函数在哪里? (3认同)
  • 现在它就在那里.感谢您的注意. (3认同)

小智 5

类似于Andreas_D所建议但使用内部类.这样,您确实可以扩展每个类,并且可以根据需要在您自己的代码中覆盖它.

interface IBird {
    public void layEgg();
}

interface IMammal {
    public void giveMilk();
}

class Bird implements IBird {
    public void layEgg() {
        System.out.println("Laying eggs...");
    }
}

class Mammal implements IMammal {
    public void giveMilk() {
        System.out.println("Giving milk...");
    }
}

class Platypus implements IMammal, IBird {

    private class LayingEggAnimal extends Bird {}
    private class GivingMilkAnimal extends Mammal {}

    private LayingEggAnimal layingEggAnimal = new LayingEggAnimal();

    private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal();

    @Override
    public void layEgg() {
        layingEggAnimal.layEgg();
    }

    @Override
    public void giveMilk() {
        givingMilkAnimal.giveMilk();
    }
}
Run Code Online (Sandbox Code Playgroud)