【问题标题】:What is the difference between inherit from an abstract class and from a concrete class? Why would we need the latter?从抽象类继承和从具体类继承有什么区别?为什么我们需要后者?
【发布时间】:2015-04-24 17:48:14
【问题描述】:

我知道 Abstract 是其他扩展的类 但是为什么要扩展一个非抽象类呢? 通常只从抽象类扩展是不是更好的约定,因为它们不能被实例化,所以它不会做奇怪的事情?

一个例子说明为什么一个人必须是抽象的/不是抽象的以显示区别会很棒。

【问题讨论】:

  • 我投票决定将此问题作为题外话结束,因为它确实应该在 Programmers.SE 上,但它会以duplicate of this question 的形式迅速关闭
  • 考虑到现在,在 Java 8 中,我们有默认方法,这实际上不是一个坏问题。
  • @alfasin 这不是一个坏问题,它只是“问和回答”
  • 我找不到适合初学者阅读的简单答案:/
  • @durron597 您发布的链接讨论了摘要与最终/密封。那不是同一个问题。此外,我没有写我的第一条评论作为对你的评论。

标签: class inheritance abstract-class


【解决方案1】:

在很多情况下,您都希望从具体类进行扩展。

考虑一个名为Device 的类。每个设备都有一个名称,可以处于三种状态,ONOFFINIT_STATE。每个设备都可以转动onoff

public class Device {
    private String name;
    private static final int ON = 1;
    private static final int OFF = 0;
    private static final int DEVICE_INIT_STATE = -1;
    private int deviceStatus = DEVICE_INIT_STATE;

    public Device(String name) {
        this.name = name; 
    }

    public final void on() {
        if (deviceStatus==OFF || deviceStatus==DEVICE_INIT_STATE) {
            deviceStatus = ON;
            System.out.println(getName() + " turned on");
        } else {
            System.out.println(getName()+" is already on");
        }
    }

    public final void off() {
        if (deviceStatus==ON) {
            deviceStatus = OFF;
            System.out.println(getName() + " turned off");
        } else {
            System.out.println(getName()+" is not on");
        }
    }

    public void undo() {
        if (deviceStatus==ON) {
            off();
        } else if(deviceStatus==OFF){
            on();
        }
    }

    public String getName() {
        return name;
    }

    protected boolean isON() {
        return deviceStatus==ON;
    }
}

考虑Stereo,它也是Device,但具有openTraycloseTraysetCd等附加功能,并且可以处于ONOFF、@987654335这5种状态@、TRAY_CLOSEINIT_STATE

public class Stereo extends Device {

    private String cd;
    private static final int TRAY_OPEN = 1;
    private static final int TRAY_CLOSE = 0;
    private static final int TRAY_INIT_STATE = -1;
    protected int trayState = TRAY_INIT_STATE;

    public Stereo(String name) {
        super(name);
    }

    public void openTray() {
        if(!isON()) {
            System.out.println(getName()+" is not on");
        } else if(trayState==TRAY_CLOSE || trayState == TRAY_INIT_STATE) {
            trayState = TRAY_OPEN;
            System.out.println("Tray opened for "+getName());
        }  else {
            System.out.println(getName()+" tray is already open");
        }

    }

    public void closeTray() {
        if(!isON()) {
            System.out.println(getName()+" is not on");
        } else if(trayState==TRAY_OPEN) {
            trayState = TRAY_CLOSE;
            System.out.println("Tray closed for "+getName());
        } else {
            System.out.println(getName()+" tray is not open");
        }

    }

    public void undo() {
        if(trayState==TRAY_OPEN) {
            closeTray();
        } else if(trayState==TRAY_CLOSE) {
            openTray();
        }
    }

    public void setCd(String cd) {
        this.cd = cd;
    }

    public String getCd() {
        return cd;
    }


}

Stereo 从Device 继承onoff 方法。您可以按如下方式实例化一个基本设备,例如灯泡:

Device lightBulb = new Device("Living room light bulb");

另一方面,您可以按如下方式实例化立体声:

Stereo stereo = new Stereo("Stereo in my heart");

从上面的例子可以看出,灯泡是基本的Device,只能转动onoff。另一方面,Stereo 是一种更专业的Device,可以转换为onoff,但也具有openTraycloseTray 功能。由于StereoDevice,它从Device 继承onoff 方法。这是一个超类有一个用例的例子,它可以被实例化并且不需要是抽象的。

【讨论】:

  • 很好的示例机器人,我想知道你能否举个例子说明为什么我不想实例化父级(抽象)?只是为了让我可以看到选项之间的明显区别(它让我疯狂地试图理解它)干杯!
  • 抽象的方法是创建 LightBulb bulb = new LightBulb() 并让它扩展抽象类 Device { } 吗?这不是很好的方法吗?为什么会这样?
  • 如果你提到你想要一个类什么时候必须是抽象的例子,我会采取不同的例子。这似乎不是你问题的一部分。发布一个新问题并让这个问题被视为已完成? ;) 回答您关于Deviceabstract 的问题。这样想,Device 类是否有一些操作宁愿让它的每个子类处理而不为它提供默认实现?如果是,则在Device 中为此操作创建一个abstract 方法并生成Device abstract
【解决方案2】:

恕我直言,您在谈论两个正交的事情。

在前者中,您要确保没有人可以实例化您的抽象类。再加上一些额外的好处,比如声明一些常用方法。

在继承中,您正在扩展一个类以添加/更新某些功能。如果您是父类,则可以实例化 - 您不需要使其抽象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 2012-11-22
    相关资源
    最近更新 更多