您能否举例说明为什么 Java 抽象方法不能存在于非抽象 class 中?

Can you give an example of why exactly a Java abstract method cannot exist in a non-abstract class?

我想要一个真实世界的类型示例来说明为什么 Java 抽象方法不能存在于非抽象 class.

我明白这不可能发生的原因 - 抽象 classes 强制执行其中包含的任何抽象方法 - 但一个可理解的具体示例确实可以帮助我在脑海中推理出来,很多谢谢。

一个抽象class意味着class不能被直接实例化。如果 class 有一个抽象方法,那么就不能直接实例化它,因为该方法没有定义。因此,任何具有抽象方法的 class 都是无法实例化的抽象 class。 Java 只是让你这样标记它。

抽象 class 和非抽象 class 之间的主要区别之一是您无法创建抽象 class 的实例。这可以防止调用没有定义的方法的情况。

所以如果我们有以下摘要class:

abstract class Elephant {    // abstract class

    public String getName() {
        return "Ollie";
    }

    public abstract void walk();   // abstract method

}

那么以下是非法的:

Elephant e = new Elephant();   // error

因为Elephant是抽象的,无法实例化。

但是为了论证,我们把Elephant设为非抽象,但允许仍然有抽象方法walk()。即我们将 Elephant 的定义更改为:

class Elephant {    // non-abstract class

    public String getName() {
        return "Ollie";
    }

    public abstract void walk();    // abstract method

}

现在如果我执行以下操作会发生什么:

Elephant e = new Elephant();   // legal since Elephant is non-abstract
e.walk();   // oops, we didn't define this anywhere

Java 编译器不允许这样做。您可能会争辩说还有其他方法可以处理这种情况,但这只是 Java 语言决定实现该功能的方式。

就像 class 中的 abstract 方法一样,interface 中的方法(隐式抽象)允许对抽象进行建模。与多种类型相关的东西,但每个部分的行为都不同。

考虑一辆简单的车辆,它可以 drive(),这是车辆的共同点。

public interface Vehicle {
    void drive();
}

现在,您无法单独创建 VehicleVehicle v = new Vehicle()。考虑 构建可以驱动 的东西的任务。你只关心它能不能驱动,而不管它做得有多精确。你谈论 抽象,但你总是 需要一个具体的实现,一些实际上能够做到的东西。这就是为什么你不能实例化一个抽象 class。它不完整,缺少一些抽象的必需部分。

因此,每辆车的驾驶方式都不同,如以下实施所示:

public class Car implements Vehicle {
    public void drive() {
        if(isEngineTurnedOn()) {
            GearState state = getCurrentGearState();
            if(state == GearState.BACKWARDS) {
                // ...
            } else {
                engine.setSpeed(currentSpeed);
            }
            // ...
        }
    }
}

public class Boat implements Vehicle {
    public void drive() {
        if(isEngineTurnedOn()) {
            rotor.setAngleInDegrees(currentAngle);              
            rotor.setSpeed(currentSpeed);
            // ...
        }
        // ...
    }
}

然后,如果您再次询问可以驱动的东西,您可以给来电者一个new Car(),它有能力这样做。由于来电者只对 drive() 感兴趣,您也可以将 new Boat() 递给他。

另一种看待这个问题的方式“为什么我必须提供我的接口的实现?”

答案是因为接口方法是隐式的abstract。因此,您必须 提供一个实现(或空体)。否则,你会得到一个编译器错误,因为没有方法体,因此没有合法的方法可以调用(JVM 不知道如何处理它 - 对于非 void return 类型,它会做什么?)。

现在,如果您将 class 声明为抽象,则不需要实现。 然后你就回到了你之前的问题,答案是一样的。无法调用抽象方法,因此允许实例化包含它们的 classes 是没有意义的。

前言:我试图让它简单和合乎逻辑,但这可能不是一个完全合乎逻辑的解释,但这肯定会帮助你在脑海中推理出来,只要知道是你必须遵守的规则。在每一种语言中,您都可能会遇到这样的规则,这些规则看起来有点混乱、有问题。

让我们试着这样理解它:

没有定义的方法是不完整的,在非抽象(完整)方法中使用抽象(不完整)方法class会增加class的不完整性,并使class 不完整。现在你不能实例化 class 因为它是不完整的(抽象的)。

这没有意义,因为你可以为此使用抽象 class,为什么要把非抽象 class 变成抽象。这就是不允许这样做的原因。

但是如果你想做这样的事情,你可以将定义的方法添加到非抽象class.