从抽象 class 继承和从具体 class 继承有什么区别?为什么我们需要后者?
What is the difference between inherit from an abstract class and from a concrete class? Why would we need the latter?
我知道摘要是 class 其他东西的延伸
但为什么要扩展非抽象 class?
仅从抽象 classes 扩展通常是更好的约定吗,因为它们不能被实例化,所以它不会做奇怪的事情?
一个例子来说明为什么必须 abstract/not 抽象来显示区别会很棒。
恕我直言,您正在谈论两个正交的事物。
在前者中你想确保没有人可以实例化你的抽象class。再加上一些额外的好东西,比如声明一些常用方法。
在继承中,您正在扩展 class 以添加/更新一些 functionality.If 您是父级 class 可以实例化 - 您不需要将其抽象化。
在很多情况下,您都希望从具体的 classes 进行扩展。
考虑一个名为 Device
的 class。每个设备都有一个名称,可以处于三种状态,ON
、OFF
或 INIT_STATE
。每个设备可以转on
或off
.
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
,但具有其他功能,例如 openTray
、closeTray
和 setCd
,并且可以处于 5 种状态即 ON
、OFF
、TRAY_OPEN
、TRAY_CLOSE
和 INIT_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
的 on
和 off
方法。您可以实例化一个基本设备,例如灯泡,如下所示:
Device lightBulb = new Device("Living room light bulb");
另一方面,您可以按如下方式实例化立体声:
Stereo stereo = new Stereo("Stereo in my heart");
从上面的例子中可以看出,灯泡是一个基本的 Device
,只能转动 on
或 off
。另一方面,Stereo
是一种更特殊的 Device
,它可以变成 on
和 off
,但也有 openTray
和 closeTray
功能。由于 Stereo
是 Device
,它继承了 Device
的 on
和 off
方法。这是一个示例,其中 super class 有一个用例,它可以被实例化并且不需要是抽象的。
我知道摘要是 class 其他东西的延伸 但为什么要扩展非抽象 class? 仅从抽象 classes 扩展通常是更好的约定吗,因为它们不能被实例化,所以它不会做奇怪的事情?
一个例子来说明为什么必须 abstract/not 抽象来显示区别会很棒。
恕我直言,您正在谈论两个正交的事物。
在前者中你想确保没有人可以实例化你的抽象class。再加上一些额外的好东西,比如声明一些常用方法。
在继承中,您正在扩展 class 以添加/更新一些 functionality.If 您是父级 class 可以实例化 - 您不需要将其抽象化。
在很多情况下,您都希望从具体的 classes 进行扩展。
考虑一个名为 Device
的 class。每个设备都有一个名称,可以处于三种状态,ON
、OFF
或 INIT_STATE
。每个设备可以转on
或off
.
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
,但具有其他功能,例如 openTray
、closeTray
和 setCd
,并且可以处于 5 种状态即 ON
、OFF
、TRAY_OPEN
、TRAY_CLOSE
和 INIT_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
的 on
和 off
方法。您可以实例化一个基本设备,例如灯泡,如下所示:
Device lightBulb = new Device("Living room light bulb");
另一方面,您可以按如下方式实例化立体声:
Stereo stereo = new Stereo("Stereo in my heart");
从上面的例子中可以看出,灯泡是一个基本的 Device
,只能转动 on
或 off
。另一方面,Stereo
是一种更特殊的 Device
,它可以变成 on
和 off
,但也有 openTray
和 closeTray
功能。由于 Stereo
是 Device
,它继承了 Device
的 on
和 off
方法。这是一个示例,其中 super class 有一个用例,它可以被实例化并且不需要是抽象的。