组合和接口在Java中的实际应用?

组合和接口在Java中的实际应用?,java,interface,composition,Java,Interface,Composition,我很难理解如何使用组合和接口来支持组合而不是继承?例如: 接口: public interface IMachine { void TurnOn(); void TurnOff(); } Machine类是Printer类的父类 public class Machine { protected boolean isOn; public Machine(boolean isOn) { this.isOn = isOn; }

我很难理解如何使用组合和接口来支持组合而不是继承?例如:

接口:

public interface IMachine {
    void TurnOn();
    void TurnOff();
}

Machine类是Printer类的父类

public class Machine {

    protected boolean isOn;

    public Machine(boolean isOn) {
        this.isOn = isOn;
    }

    public void TurnOn() {
        isOn = true;
        System.out.println("Machine is on !");
    }

    public void TurnOff() {
        isOn = false;
    }

}


现在,如果我创建一个实现IMachine接口的Printer类,它将实现IMachine接口的方法。但假设我创建了一个实现IMachine接口的时钟类,那么我必须再次实现这些方法。有没有更有效的方法,我们使用组合和接口,并将方法委托给机器类?

通过继承,您将拥有一个具有共享逻辑的基类,以及使用该共享逻辑的子类。该基类的任何公共方法都是共享API

通过组合,接口定义了共享API,每个实现类(以前是子类的类)将把这些调用委托给一个实际具有共享逻辑的复合类

继承权

构图

Machine
的用户仍将看到相同的公共API,
hearter
的用户仍将看到相同的公共API,但逻辑已重新定位


这允许
加热器
实现多个独立的“功能”,这在使用继承时是不可能的。

通过继承,您将拥有一个具有共享逻辑的基类,以及使用该共享逻辑的子类。该基类的任何公共方法都是共享API

通过组合,接口定义了共享API,每个实现类(以前是子类的类)将把这些调用委托给一个实际具有共享逻辑的复合类

继承权

构图

Machine
的用户仍将看到相同的公共API,
hearter
的用户仍将看到相同的公共API,但逻辑已重新定位


这允许加热器实现多个独立的“功能”,这在使用继承时是不可能的。

组合通常在“has a”关系中指代。例如,在这种情况下,如果您有PowerSwitch对象的概念,就可以使用composition。这将在机器“具有”电源开关的通知中实现

继承通常被称为“是一种”关系,就像打印机中的“是一种”机壳一样

使用PowerSwitch对象,您可以包含打印机和时钟的功能,可能是在抽象机器中

public abstract class AbstractMachine implements IMachine {
  private PowerSwitch machinePowerSwitch;

  public void turnOff() {
    machinePowerSwitch.turnOff();
  }

  public void turnOn() {
    machinePowerSwitch.turnOn();
  }

  public void isOn() {
    return machinePowerSwitch.getPowerState();
  }
}
或者类似的东西。打印机和时钟都可以扩展机器


编辑:重读这个问题,我发现你想要的是合成而不是继承(我读这个问题是因为你想两者兼用)。在这种情况下,只需直接在Printer/Clock类中使用电源开关。

合成通常指“has a”关系。例如,在这种情况下,如果您有PowerSwitch对象的概念,就可以使用composition。这将在机器“具有”电源开关的通知中实现

继承通常被称为“是一种”关系,就像打印机中的“是一种”机壳一样

使用PowerSwitch对象,您可以包含打印机和时钟的功能,可能是在抽象机器中

public abstract class AbstractMachine implements IMachine {
  private PowerSwitch machinePowerSwitch;

  public void turnOff() {
    machinePowerSwitch.turnOff();
  }

  public void turnOn() {
    machinePowerSwitch.turnOn();
  }

  public void isOn() {
    return machinePowerSwitch.getPowerState();
  }
}
或者类似的东西。打印机和时钟都可以扩展机器


编辑:重读这个问题,我发现你想要的是合成而不是继承(我读这个问题是因为你想两者兼用)。在这种情况下,只需在打印机/时钟类中直接使用电源开关。

简单的解决方案是。。。只要让
机器实现IMachine
,将
开启()
关闭()
设置为
最终版
,让
打印机
时钟扩展机器
@Turing85组合的要点是不使用继承。简单的解决方案是。。。只要让
机器实现IMachine
,将
开启()
关闭()
设置为
最终版
,让
打印机
时钟扩展机器
@Turing85组合的要点是不使用继承。
public abstract class AbstractMachine implements IMachine {
  private PowerSwitch machinePowerSwitch;

  public void turnOff() {
    machinePowerSwitch.turnOff();
  }

  public void turnOn() {
    machinePowerSwitch.turnOn();
  }

  public void isOn() {
    return machinePowerSwitch.getPowerState();
  }
}