在Java中处理多重继承

在Java中处理多重继承,java,inheritance,multiple-inheritance,Java,Inheritance,Multiple Inheritance,我有以下基类层次结构: 索引(摘要) RootIndex AbstractSubIndex(摘要) 然后我还有两门课: KPI,它应该继承AbstractSubIndex,并添加自身独有的功能 子索引,它应该继承抽象子索引的功能以及根索引中的功能。我会选择默认方法(Java8),但我有一些无法在interfaces(实例变量)中编写的代码 更新 请注意,Index具有默认的构造后功能,该功能在其他类中继承;此构建后功能必须执行一次。组合将迫使它至少执行两次,这使得组合对我来说是一个不

我有以下基类层次结构:

  • 索引
    (摘要)
    • RootIndex
    • AbstractSubIndex
      (摘要)
然后我还有两门课:

  • KPI
    ,它应该继承
    AbstractSubIndex
    ,并添加自身独有的功能
  • 子索引
    ,它应该继承
    抽象子索引
    的功能以及
    根索引
    中的功能。我会选择默认方法(Java8),但我有一些无法在
    interface
    s(实例变量)中编写的代码
更新

请注意,
Index
具有默认的构造后功能,该功能在其他类中继承;此构建后功能必须执行一次。组合将迫使它至少执行两次,这使得组合对我来说是一个不可行的解决方案

结束更新

我找不到任何非冗余的方法来解决这个问题


有什么想法吗?

解决这些问题的标准方法是授权


根据需要定义接口及其层次结构。定义具体的类。当属于不同继承分支的类A和类B共享功能时,应该在类C中实现它,并从A和B调用C的方法。

使用组合而不是继承。在类中为AbstractIndex或RootIndex(甚至两个字段)声明一个字段。

好的,据我所知,我认为以下内容可能会将其删除。假设您的
索引
类为

abstract class Index {

    public Index() {
        // your code here
        // ...

        postConstruct();
    }

    void postConstruct() {
        // your post construction stuff
    }

    // assumed just one abstract method, may be a thousand like it
    abstract void foo(); 
}
而您的派生类型为

class RootIndex extends Index {
    // ...

    @Override
    void foo() {
        // your stuff
    }

    public void bar() {
        // your additional stuff
    }
}

我会这样做。创建一个界面,公开
RootIndex
附加功能的签名:

interface AdditionalFunctionalityInterface {
    void bar();
}
并使
RootIndex
实现它。然后,我将围绕你的一次施工后工作如下:

class SubIndex extends AbstractIndex implements AdditionalFunctionalityInterface {

    private class AuxRootIndex extends RootIndex {
        @Override
        void postConstruct() {
            // DON'T do what super.postConstruct() does
            // might as well be empty if you wish
        }
    }

    // composition
    private AuxRootIndex myRootIndex;

    @Override
    void foo() {
        // your stuff

        // a little bit unclear here, you can keep the one from
        // AbstractIndex or the one from RootIndex if you want
        myRootIndex.foo();
    }


    @Override
    public void bar() {
        myRootIndex.bar();
    }
}

我希望,除非有其他条件和限制,否则上述措施应该会奏效。您的代码可能与上面的格式不同,但您可以通过将其他代码提取到单独的方法中来实现此格式。

对于我来说,奇怪的是,此解决方案基于组合-感谢@kinga93和@AlexR的建议以及从头开始的面向方面的设计-,但是对基类的原始代码进行了更多的调整,这是我尽力避免的

请注意,我已经将@webuster的解决方案标记为可接受的解决方案,因为它更简单,并且能够完成工作。我之所以发布这篇文章,是因为这是我最终选择的,因为从设计的角度来看,这对我来说更有意义,而且是为了防止有人需要它

  • 我从
    RootIndex
    中获取了不基于
    Index
    的代码,并将其包装在类
    parentbehavior
    中,并在其位置添加了一个引用
  • 我在
    AbstractSubIndex
    中也做了同样的操作,将不基于
    Index
    的代码包装到另一个类
    ChildBehavior
    ,并在其位置添加一个引用
  • 我在
    SubIndex
    中使用了composition,引用了
    ParentBehavior
    ChildBehavior
    ,同时继承了
    AbstractSubIndex
  • 我在
    KPI
    中再次使用了composition,它继承了
    AbstractSubIndex
    ,同时引用了
    ChildBehavior
  • 最后的代码是这样的:

    class ParentBehavior {
        // functionality that exists in RootIndex and SubIndex, which does not
        // depend on Index.
    }
    
    class ChildBehavior {
        // functionality that exists in SubIndex and KPI, which does not depend
        // on Index.
    }
    
    abstract class Index {
        // contains post-construction code.
        void foo();
    }
    
    class RootIndex extends Index {
        ParentBehavior parentBehavior;
    }
    
    abstract class AbstractSubIndex extends Index {
        // shared code between SubIndex and KPI
        ChildBehavior childBehavior;
    }
    
    class SubIndex extends AbstractSubIndex {
        ParentBehavior parentBehavior;
    }
    
    class KPI extends AbstractSubIndex {
        // unique functionality for KPI
    }
    

    这样,
    子索引
    KPI
    抽象子索引
    继承
    索引
    的基本功能,从而不重复地从
    索引
    继承所需的后期构造功能,同时只从基类获得所需的功能(通过
    ParentBehavior
    ChildBehavior
    ).

    我知道
    子索引
    应该从这两个类继承功能,并且它们可以很容易地通过一些嵌套类继承。
    子索引
    应该从哪种类型派生?它既从
    抽象子索引
    派生,也从
    根索引
    派生。这两个类都具有构造所需的功能ode>子索引。我看到您需要在
    子索引
    中提供这两种功能,但我是从编译器的类型角度提出的。它仍然必须有一个类型。它不能同时充当类型
    a
    B
    ,除非它们中最多有一个是类,但您知道。抱歉,我误解了您的问题 :) . 从逻辑上讲,它是一个
    抽象子索引
    。在问题中我忘了写一些东西,这使得这个解决方案对我来说不可行。索引中有默认的后期构造功能,它在RootIndex和AbstractSubIndex中都是继承的。在您提到的所有情况下,Composition将至少执行此功能两次。很抱歉,我之前没有提到这一部分;现在更新。谢谢你的回答,但我有点不清楚。我想你的意思是我用作文,这对我来说是行不通的。请检查问题中的更新部分。
    索引的默认后期构造逻辑必须在每个实例、每个子类或应用程序生命周期内运行一次?每个类/子类实例运行一次。这正是我要发布的内容。简单的构图不是答案,装饰师才是。你知道,我以前听说过装饰师,但从没想过这就是答案。我确实需要修改设计模式。谢谢你的提示。:)
    
    class ParentBehavior {
        // functionality that exists in RootIndex and SubIndex, which does not
        // depend on Index.
    }
    
    class ChildBehavior {
        // functionality that exists in SubIndex and KPI, which does not depend
        // on Index.
    }
    
    abstract class Index {
        // contains post-construction code.
        void foo();
    }
    
    class RootIndex extends Index {
        ParentBehavior parentBehavior;
    }
    
    abstract class AbstractSubIndex extends Index {
        // shared code between SubIndex and KPI
        ChildBehavior childBehavior;
    }
    
    class SubIndex extends AbstractSubIndex {
        ParentBehavior parentBehavior;
    }
    
    class KPI extends AbstractSubIndex {
        // unique functionality for KPI
    }