原文: https://www.programiz.com/java-programming/abstract-classes-methods
抽象类是无法实例化的类(我们无法创建抽象类的对象)。 在 Java 中,我们使用abstract
关键字来声明一个抽象类。
abstract class Animal {
//attributes and methods
}
如果尝试创建抽象类的对象,则会出现编译错误。 例如,
Animal a1 = new Animal()
它将产生一个编译错误:
Animal is abstract; cannot be instantiated
尽管不能实例化抽象类,但是我们可以从中创建子类。 我们可以创建子类的对象来访问抽象类的成员。
在详细了解它之前,我们需要了解抽象方法。
我们使用相同的关键字abstract
创建抽象方法。 声明了一个抽象方法而没有实现。 例如,
abstract void makeSound();
在这里,makeSound()
是一种抽象方法。makeSound()
的主体被;
取代。
重要的是要注意,只有抽象类才能包含抽象方法。 如果我们在不是抽象的类中包含抽象方法,则会出现错误。
抽象类可以包含抽象方法和非抽象方法。 这是一个例子。
abstract class Animal {
public void displayInfo() {
System.out.println("I am an animal.");
}
abstract void makeSound();
}
在上面的示例中,我们创建了一个抽象类Animal
。 它包含抽象方法makeSound()
和非抽象方法displayInfo()
。
抽象类无法实例化。 要访问抽象类的成员,我们必须继承它。 例如
abstract class Animal {
public void displayInfo() {
System.out.println("I am an animal.");
}
}
class Dog extends Animal {
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.displayInfo();
}
}
输出:
I am an animal.
在上面的示例中,我们创建了一个抽象类Animal
。 我们无法创建Animal
的对象。 要访问Animal
的displayInfo()
,我们继承了Animal
的子类Dog
。
然后,我们使用Dog
的d1
对象访问方法displayInfo()
。
在 Java 中,必须在子类中覆盖超类的抽象方法。 这是因为子类继承了超类的抽象方法。
由于我们的子类包含抽象方法,因此我们需要覆盖它们。
注意:如果子类也被声明为抽象,则不必强制覆盖抽象方法。
abstract class Animal {
abstract void makeSound();
public void eat() {
System.out.println("I can eat.");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Bark bark");
}
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.makeSound();
d1.eat();
}
}
输出:
Bark bark.
I can eat.
在上面的示例中,我们创建了一个抽象类Animal
。 该类包含一个抽象方法makeSound()
和一个非抽象方法eat()
。
我们从超类Animal
继承了子类Dog
。 在此,子类Dog
覆盖了抽象方法displayInfo()
。
然后,我们创建了Dog
的对象d1
。 然后使用该对象调用d1.displayInfo()
和d1.eat()
方法。
与非抽象类相似,我们使用super
关键字从子类访问抽象类的构造器。 例如,
abstract class Animal {
Animal() {
….
}
}
class Dog extends Animal {
Dog() {
super();
...
}
}
在这里,我们已经使用Dog
的构造器中的super()
来访问Animal
的构造器。
注意,super
应该始终是子类构造器的第一条语句。 访问 Java super
关键字了解更多信息。
抽象是面向对象编程的重要概念。 抽象仅显示所需的信息,所有不必要的细节都保持隐藏。 这使我们可以通过使用更简单,更高级的想法省略或隐藏细节来管理复杂性。
抽象的实际示例可以是摩托车制动器。 我们知道刹车的作用。 当我们踩刹车时,摩托车将停止。 但是,制动器的工作对我们而言是隐藏的。
隐藏制动器工作原理的主要优点是,现在制造商可以为不同的摩托车实现不同的制动器,但是制动器的作用是相同的。
让我们举一个例子来帮助我们更好地理解 Java 抽象。
abstract class Animal {
abstract void makeSound();
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Bark bark.");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Meows ");
}
}
class Main {
public static void main(String[] args) {
Dog d1 = new Dog();
d1.makeSound();
Cat c1 = new Cat();
c1.makeSound();
}
}
输出:
Bark bark
Meows
在上面的示例中,我们创建了超类Animal
。 超类Animal
具有抽象方法makeSound()
。
无法在Animal
内部实现makeSound()
方法。 这是因为每种动物都会发出不同的声音。 因此,Animal
的所有子类都将具有makeSound()
的不同实现。
我们无法以对Animal
的所有子类都正确的方式在Animal
中实现makeSound()
。 因此,Animal
中makeSound()
的实现保持隐藏状态。
在以上示例中,Dog
自行实现了makeSound()
,而Cat
自行实现了makeSound()
。
-
我们使用
abstract
关键字来创建抽象类和方法。 -
抽象方法没有任何实现(方法体)。
-
包含抽象方法的类也应该是抽象的。
-
我们不能创建抽象类的对象。
-
为了实现抽象类的函数,我们从其继承子类并创建该子类的对象。
-
子类必须覆盖抽象类的所有抽象方法。 但是,如果子类被声明为抽象的,则不必强制覆盖抽象方法。
-
我们可以使用抽象类的引用来访问抽象类的静态属性和方法。 例如
Animal.staticMethod();
在 Java 中,接口类似于抽象类。 但是,接口没有任何非抽象方法。 在下一个教程中,我们将学习有关接口的更多信息。