【问题标题】:"An abstract class can not be instantiated in JAVA" What purpose does this property serve?“无法在 JAVA 中实例化抽象类”该属性有什么用途?
【发布时间】:2018-09-10 19:15:10
【问题描述】:

抽象类可以扩展,因此抽象类的所有类成员(变量+方法)都可以从扩展抽象类的子类中调用/使用。 那么,为什么JAVA禁止创建抽象类的对象呢?

【问题讨论】:

  • 假设一个类有一个抽象方法String foo()。假设你创建了这个抽象类的一个实例,然后在这个实例上调用foo()。您希望会发生什么?

标签: java oop abstract-class


【解决方案1】:

Java 不允许直接实例化抽象类,因为没有意义……如果你有:

abstract class Person {
   abstract String getName();
   int getAge() {
      return 72;
   }
}

并且被允许这样称呼它

public static void main(String... args) {
    System.out.println(new Person().getName());
}

那么事情就没有意义了。

但是,既然抽象类可以实现了方法,那么您的评论:

所以抽象类的所有类成员(变量+方法)都可以从扩展抽象类的子类中调用/使用。

只是说你错过了来自子类的部分,子类被认为是具体的。换句话说,这些方法和变量仍然可以使用,但它们必须用于具体类型(在上面的示例中,这将是一个为 getName 提供实现的类型,以使事情再次变得有意义)

【讨论】:

  • 您可以拥有一个没有未实现/抽象方法的抽象类。
  • @lexicore true,但这在这种情况下无关紧要,因为 java 会阻止你实例化它......
  • 这正是我的观点。 Java 不允许实例化抽象类,无论它是否具有抽象/未实现的方法。所以用抽象方法争论(就像你做的那样)没有抓住重点。
  • @lexicore 你的逻辑有缺陷。大多数抽象类都有抽象方法。正如答案所示,实例化它们没有任何意义。当然,您可以在特殊情况下拥有没有任何抽象方法的抽象类。但在这种情况下,抽象恰恰意味着基类应该始终是子类,无论出于何种原因。在这种情况下,编译器不应该对一般规则做出例外,因为如果开发人员希望该类是可实例化的,那么该类根本不应该是抽象的。
  • @lexicore 不,但这正是重点。如果不是因为抽象方法,Java 会有理由让你实例化它。 但问题是您可以添加抽象方法 - 抽象仅取决于方法未实现这一事实...除了抽象方法(存在或未来)?
【解决方案2】:

使类抽象是开发人员指定某些类可能不被实例化的一种工具。

这可能有很多原因。

其中一个典型用法是template method pattern,您在其中声明使用抽象基类中的抽象方法,子类的具体实现实现声明的抽象方法。

或者您可能有一个复杂的类层次结构,其中超类本质上不是具体的。例如,地理标记语言 3.2.1 中的 PolygonType 层次结构:

PolygonType extends
AbstractSurfaceType extends
AbstractGeometricPrimitiveType extends
AbstractGeometryType extends
AbstractGMLType

设计者可能已经决定只有像PolygonType 这样的具体类应该是可实例化的,而不是像AbstractGeometryType 这样的更高级别的抽象。制作所有的Abstract*abstract实际上是对使用此架构或库的开发人员强制执行此想法。

【讨论】:

    【解决方案3】:

    创建抽象类是有原因的。假设您有一个工厂类Car 来创建不同汽车类型的汽车实例。所以每辆车都会有一些共同的属性,比如轮子的数量、颜色、速度计等。但是每辆汽车在创建它们之前都必须具有所有这些属性。但是汽车可以是不同类型的,例如卡车(重型车辆),Mini Van(中型)和小型家用车等。但是每辆汽车都有其不常见的特定属性。例如发动机。因此,作为汽车架构的设计者,您会将汽车的所有公共属性放在一个公共类中,但这样的类的实例化没有任何意义。因此,您将使其抽象化,并强制将类继承到特定车辆类型,如下所示:-

       public abstract class Utility{
       }
    
       public class Truck extends Utility{
       }
    
       public class MiniVan extends Utility{
       } 
    

    【讨论】:

      【解决方案4】:

      抽象类旨在提供由其所有直接和间接子类共享的部分实现。通常,一个抽象类将包含至少一个抽象方法。如果是这样,那么抽象类的每个具体子类都必须声明这样的方法。没有每个抽象方法的实现,抽象类就无法完全实现。

      考虑下面的例子。

      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 类没有提供足够的信息来使实例化变得有意义。

      抽象类的目的是重用代码,并允许通过抽象超类引用多态地处理不同的子类类型。

      【讨论】:

        【解决方案5】:

        那么,为什么JAVA禁止创建抽象类的对象呢?

        在抽象类有抽象方法的情况下,限制的原因是抽象方法不起作用。例如,鉴于此:

        public abstract class Animal {
            public abstract int getLegCount();
        }
        

        这个语句应该做什么?

        System.out.println("An animal has " + (new Animal()).getLegCount() + " legs");
        

        允许您创建不起作用的实例是一件坏事。


        在没有抽象方法的情况下,限制是为了一致性。允许您实例化 一些 抽象方法并没有任何实际用途。在这种情况下,如果您想要实例化该类,您只需从类声明中删除 abstract 关键字即可。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-06
          • 2015-08-04
          • 1970-01-01
          • 2021-12-29
          • 2017-02-05
          • 2021-06-11
          相关资源
          最近更新 更多