# Java 中的抽象类

> 原文： [https://beginnersbook.com/2013/05/java-abstract-class-method/](https://beginnersbook.com/2013/05/java-abstract-class-method/)

使用`abstract`关键字声明的类称为抽象类。它可以有抽象方法（没有主体的方法）以及具体方法（常规方法与主体）。普通类（非抽象类）不能有抽象方法。在本指南中，我们将了解什么是抽象类，我们使用它的原因以及在 Java 中使用它时必须记住的规则。

> 抽象类不能**实例化**，这意味着你不能创建它的**对象**。为什么？我们将在本指南的后面部分讨论。

## 为什么我们需要一个抽象类？

假设我们有一个类`Animal`有一个方法`sound()`和它的子类（参见[继承](https://beginnersbook.com/2013/03/inheritance-in-java/)），如`Dog`，`Lion`，`Horse`，`Cat`等。动物的声音因动物而异，没有必要在父类中实施这种方法。这是因为每个子类都必须覆盖此方法以给出自己的实现细节，例如`Lion`类将在此方法中说`"Roar"`而`Dog`类将说`"Woof"`。

因此，当我们知道所有动物子类将会并且应该重写此方法时，那么在父类中实现此方法是没有意义的。因此，使这个方法抽象是一个很好的选择，因为通过使这个方法抽象我们强制所有子类实现这个方法（否则你会得到编译错误），我们也不需要在父类中给这个方法任何实现。

由于`Animal`类有一个抽象方法，你必须要声明这个类是抽象的。

现在每个动物都必须有声音，通过使这个方法抽象化，我们强制要求子类为这个方法提供实现细节。这样我们就可以确保每只动物都有声音。

## 抽象类示例

```java
//abstract parent class
abstract class Animal{
   //abstract method
   public abstract void sound();
}
//Dog class extends Animal class
public class Dog extends Animal{

   public void sound(){
	System.out.println("Woof");
   }
   public static void main(String args[]){
	Animal obj = new Dog();
	obj.sound();
   }
}
```

输出：

```java
Woof
```

因此，对于这种情况，我们通常将类声明为抽象类，然后**具体类**扩展这些类并相应地重写方法，并且也可以拥有自己的方法。

## 抽象类声明

抽象类概述了方法，但未必实现所有方法。

```java
//Declaration using abstract keyword
abstract class A{
   //This is abstract method
   abstract void myMethod();

   //This is concrete method with body
   void anotherMethod(){
      //Does something
   }
}
```

## 规则

**注 1：**正如我们在上面的例子中所看到的，有些情况下很难或经常不必在父类中实现所有方法。在这些情况下，我们可以将父类声明为`abstract`，这使得它成为一个特殊的类，它本身并不完整。

从抽象类派生的类必须实现在父类中声明为抽象的所有方法。

**注 2：**抽象类无法实例化，这意味着你无法创建它的对象。要使用此类，您需要创建另一个扩展此类的类并提供抽象方法的实现，然后您可以使用该子类的对象来调用父类的非抽象方法以及实现的方法（那些在父类中是抽象的，但在子类中实现）。

**注 3：**如果一个孩子没有实现抽象父类的所有抽象方法，那么子类也必须被声明为`abstract`。

> **你知道吗？** 由于抽象类也允许具体方法，因此它不提供 100%抽象。你可以说它提供了部分抽象。抽象是一个过程，您只显示“相关”数据并从用户“隐藏”对象的不必要细节。
> 
> 另一方面，[接口](https://beginnersbook.com/2013/05/java-interface/)用于 100%抽象（这里有关[抽象](https://beginnersbook.com/2013/03/oops-in-java-encapsulation-inheritance-polymorphism-abstraction/)的更多信息）。
> 您可能还想阅读： [Java 中抽象类和接口之间的区别](https://beginnersbook.com/2013/05/abstract-class-vs-interface-in-java/)

### 为什么我们不能创建抽象类的对象？

因为这些类是不完整的，所以它们具有没有主体的抽象方法，所以如果 java 允许你创建这个类的对象，那么如果有人使用该对象调用抽象方法那么会发生什么？没有实际的方法实现调用。
也因为一个对象是具体的。抽象类就像一个模板，所以你必须先扩展它并在它之前构建它。

### 用于演示不允许创建抽象类的对象的示例

如上所述，我们无法实例化抽象类。该程序抛出编译错误。

```java
abstract class AbstractDemo{
   public void myMethod(){
      System.out.println("Hello");
   }
   abstract public void anotherMethod();
}
public class Demo extends AbstractDemo{

   public void anotherMethod() { 
        System.out.print("Abstract method"); 
   }
   public static void main(String args[])
   { 
      //error: You can't create object of it
      AbstractDemo obj = new AbstractDemo();
      obj.anotherMethod();
   }
}

```

输出：

```java
Unresolved compilation problem: Cannot instantiate the type AbstractDemo
```

注意：扩展抽象类的类必须实现它的所有抽象方法，否则你也必须声明该类抽象。

## 抽象类 vs 具体类

非抽象的类称为 **具体类**。在我们在本指南开头看到的上述例子中，`Animal`是一个抽象类，`Cat`，`Dog`和`Lion`是具体的课程。

**要点：**

1.  除非被其他类扩展，否则抽象类没有用处。
2.  如果在类中声明**抽象方法**，那么您也必须声明类抽象。你不能在具体的类中使用抽象方法。反之亦然并非总是如此：如果一个类没有任何抽象方法，那么它也可以被标记为抽象。
3.  它也可以有非抽象方法（具体）。

我已经在单独的教程中介绍了抽象方法的规则和示例，你可以在这里找到指南： [Java 中的抽象方法](https://beginnersbook.com/2014/01/abstract-method-with-examples-in-java/)
现在让我们看一些基本知识和抽象方法的例子。

1）抽象方法没有正文。

2）始终以**分号**（`;`）结束声明。

3）必须[覆盖](https://beginnersbook.com/2014/01/method-overriding-in-java-with-example/)。必须扩展抽象类，并且必须以相同的方式覆盖抽象方法。

4）必须将类声明为抽象的抽象方法。

**注意：**扩展抽象类的类必须覆盖所有抽象方法。

## 抽象类和方法的示例

```java
abstract class MyClass{
   public void disp(){
     System.out.println("Concrete method of parent class");
   }
   abstract public void disp2();
}

class Demo extends MyClass{
   /* Must Override this method while extending
    * MyClas
    */
   public void disp2()
   {
       System.out.println("overriding abstract method");
   }
   public static void main(String args[]){
       Demo obj = new Demo();
       obj.disp2();
   }
}

```

输出：

```java
overriding abstract method

```