【发布时间】:2018-09-10 19:15:10
【问题描述】:
抽象类可以扩展,因此抽象类的所有类成员(变量+方法)都可以从扩展抽象类的子类中调用/使用。 那么,为什么JAVA禁止创建抽象类的对象呢?
【问题讨论】:
-
假设一个类有一个抽象方法
String foo()。假设你创建了这个抽象类的一个实例,然后在这个实例上调用foo()。您希望会发生什么?
标签: java oop abstract-class
抽象类可以扩展,因此抽象类的所有类成员(变量+方法)都可以从扩展抽象类的子类中调用/使用。 那么,为什么JAVA禁止创建抽象类的对象呢?
【问题讨论】:
String foo()。假设你创建了这个抽象类的一个实例,然后在这个实例上调用foo()。您希望会发生什么?
标签: java oop abstract-class
Java 不允许直接实例化抽象类,因为没有意义……如果你有:
abstract class Person {
abstract String getName();
int getAge() {
return 72;
}
}
并且被允许这样称呼它
public static void main(String... args) {
System.out.println(new Person().getName());
}
那么事情就没有意义了。
但是,既然抽象类可以实现了方法,那么您的评论:
所以抽象类的所有类成员(变量+方法)都可以从扩展抽象类的子类中调用/使用。
只是说你错过了来自子类的部分,子类被认为是具体的。换句话说,这些方法和变量仍然可以使用,但它们必须用于具体类型(在上面的示例中,这将是一个为 getName 提供实现的类型,以使事情再次变得有意义)
【讨论】:
使类抽象是开发人员指定某些类可能不被实例化的一种工具。
这可能有很多原因。
其中一个典型用法是template method pattern,您在其中声明使用抽象基类中的抽象方法,子类的具体实现实现声明的抽象方法。
或者您可能有一个复杂的类层次结构,其中超类本质上不是具体的。例如,地理标记语言 3.2.1 中的 PolygonType 层次结构:
PolygonType extends
AbstractSurfaceType extends
AbstractGeometricPrimitiveType extends
AbstractGeometryType extends
AbstractGMLType
设计者可能已经决定只有像PolygonType 这样的具体类应该是可实例化的,而不是像AbstractGeometryType 这样的更高级别的抽象。制作所有的Abstract*abstract实际上是对使用此架构或库的开发人员强制执行此想法。
【讨论】:
创建抽象类是有原因的。假设您有一个工厂类Car 来创建不同汽车类型的汽车实例。所以每辆车都会有一些共同的属性,比如轮子的数量、颜色、速度计等。但是每辆汽车在创建它们之前都必须具有所有这些属性。但是汽车可以是不同类型的,例如卡车(重型车辆),Mini Van(中型)和小型家用车等。但是每辆汽车都有其不常见的特定属性。例如发动机。因此,作为汽车架构的设计者,您会将汽车的所有公共属性放在一个公共类中,但这样的类的实例化没有任何意义。因此,您将使其抽象化,并强制将类继承到特定车辆类型,如下所示:-
public abstract class Utility{
}
public class Truck extends Utility{
}
public class MiniVan extends Utility{
}
【讨论】:
抽象类旨在提供由其所有直接和间接子类共享的部分实现。通常,一个抽象类将包含至少一个抽象方法。如果是这样,那么抽象类的每个具体子类都必须声明这样的方法。没有每个抽象方法的实现,抽象类就无法完全实现。
考虑下面的例子。
public abstract class Shape {
public abstract void draw();
}
public class Circle extends Shape {
@Override
public void draw() {
// draw a circle
}
}
public class Square extends Shape {
@Override
public void draw() {
// draw a square
}
}
允许实例化一个 Shape 对象是没有意义的,因为如果它不知道它是什么类型的形状,它就不知道如何绘制自己。 Shape 类没有提供足够的信息来使实例化变得有意义。
抽象类的目的是重用代码,并允许通过抽象超类引用多态地处理不同的子类类型。
【讨论】:
那么,为什么JAVA禁止创建抽象类的对象呢?
在抽象类有抽象方法的情况下,限制的原因是抽象方法不起作用。例如,鉴于此:
public abstract class Animal {
public abstract int getLegCount();
}
这个语句应该做什么?
System.out.println("An animal has " + (new Animal()).getLegCount() + " legs");
允许您创建不起作用的实例是一件坏事。
在没有抽象方法的情况下,限制是为了一致性。允许您实例化 一些 抽象方法并没有任何实际用途。在这种情况下,如果您想要实例化该类,您只需从类声明中删除 abstract 关键字即可。
【讨论】: