前言
在上篇中我们学习到了继承的概念、语法等等,那么小编将来为大家方享下一篇Java中的抽象类。
1.抽象类的概念
2.抽象类的语法
3.抽象类的特性
4.抽象类的作用
一:讲到抽象类,大家是不是会很迷惑什么是抽象类?
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。例如如图:
说明:
1.矩形、三角形、圆形都是图形,因此和Shape类的惯性应该是继承关系。
2.虽然图形图Shape中也存在draw的方法,但由于shape类并不是具体的图形,因此其内部的draw方法实际是没有办法实现的。
3.由于shape类没有办法描述一个具体的图形,导致其draw()方法无法具体实现,因此可以将shape类设计为“抽象类”。
像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方(abstractmethod), 包含抽象方法的类我们称为抽象类(abstract class).在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法。
二:那么抽象类有哪些语法呢?
Java中的抽象类是一种不能被实例化的类,它主要用于被其他类继承。抽象类通常包含抽象方法,这些方法是没有具体实现的方法,只是声明了方法的签名,让子类去实现这些方法。抽象类通过abstract关键字来声明。
abstract class ClassName {
// 成员变量
// 构造方法(可选)
// 抽象方法
abstract void methodName();
// 非抽象方法(可选)
void anotherMethodName() {
// 方法实现
}
// 抽象类中可以包含静态方法
static void staticMethodName() {
// 方法实现
}
// 抽象类中也可以包含静态代码块、初始化块等
}
①抽象方法:在抽象类中,至少有一个方法是抽象方法。抽象方法用abstract关键字声明,并且没有方法体(即没有大括号{}包围的代码)。
②构造方法:抽象类可以有构造方法,但主要用途是供子类在构造实例时调用父类的构造方法,进行初始化操作。抽象类不能被实例化,因此不能直接调用其构造方法。
③继承:抽象类的主要用途是被其他类继承。继承抽象类的子类必须实现所有继承的抽象方法,除非子类也是抽象类。
④非抽象方法:抽象类中可以包含非抽象方法(即实现了具体逻辑的方法)。
⑤静态成员:抽象类中可以包含静态成员(静态变量、静态方法、静态代码块等),这些静态成员可以直接通过类名来访问
abstract class Animal {
String name;
Animal(String name) {
this.name = name;
}
// 抽象方法
abstract void makeSound();
// 非抽象方法
void eat() {
System.out.println(name + " is eating.");
}
}
class Dog extends Animal {
Dog(String name) {
super(name);
}
// 实现抽象方法
@Override
void makeSound() {
System.out.println(name + " says Woof!");
}
}
class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.makeSound();
dog.eat();
}
}
Animal是一个抽象类,它有一个抽象方法makeSound()。Dog类继承了Animal类,并实现了makeSound()方法。这样,Dog类就可以被实例化了。
三:抽象类的特性
1. 不能被实例化:抽象类不能被直接实例化。也就是说,你不能使用new关键字来创建抽象类的对象。这是因为抽象类通常包含未实现的方法,这些方法需要由子类来提供具体的实现。
2. 可以包含抽象方法:抽象类可以包含抽象方法,这是没有方法体的方法,仅声明了方法的签名。抽象方法用abstract关键字标记。抽象类也可以不包含任何抽象方法,但这样的抽象类主要是用于被其他类继承,并限制该类的实例化。
3. 可以被继承:其他类(无论是抽象类还是非抽象类)都可以继承抽象类。当子类继承抽象类时,它必须实现父类中所有的抽象方法(除非子类本身也是抽象类)。
4. 可以有构造方法:尽管抽象类不能被直接实例化,但它们可以有构造方法。这些构造方法主要用于被子类在创建实例时调用,以便进行初始化操作。
5. 可以有非抽象方法和字段:抽象类不仅限于包含抽象方法,它还可以包含已经实现的方法(即非抽象方法)和字段。这些方法和字段可以被子类继承和使用。
6. 可以作为类型引用:尽管你不能直接实例化抽象类,但你可以使用抽象类作为类型引用,比如声明类的成员变量、方法的返回类型、方法的参数等。
7. 静态成员:抽象类中可以包含静态成员(静态变量、静态方法、静态代码块等)。这些静态成员属于类本身,而不是类的实例,因此它们可以通过类名直接访问,而无需创建类的实例。
8. 访问修饰符:抽象类和抽象方法都可以使用访问修饰符(如public、protected和private)来指定它们的可见性。然而,由于抽象方法需要在子类中被实现,因此它们通常被声明为public或protected,以确保子类可以访问它们。
9. 抽象类的最终用途:抽象类的最终用途是提供一个或多个抽象方法的框架,这些方法将由继承抽象类的子类来具体实现。通过这种方式,抽象类促进了代码的复用和模块化,同时强制子类实现特定的行为。
10. 抽象类与接口的区别:虽然抽象类和接口都用于定义类的规范,但它们在实现和使用上有所不同。接口是纯粹的抽象,只能包含抽象方法和常量,而抽象类可以包含已实现的方法和变量。此外,一个类只能继承一个抽象类(单继承),但可以实现多个接口(多实现)。
四:抽象类的作用
1. 定义通用行为和属性
抽象类用于定义一组相关类的共同行为和属性。通过抽象类,开发者可以将这些共同的行为和属性抽象为方法或属性,并在抽象类中进行声明或初步实现。子类继承抽象类后,可以直接使用这些通用的方法和属性,避免了重复编写相同的代码,提高了代码的重用性和可维护性。
2. 强制子类实现特定行为
抽象类中可以包含抽象方法,这些方法没有具体的实现,只有方法的声明。子类继承抽象类后,必须实现所有继承的抽象方法,否则子类也必须被声明为抽象类。这种机制强制子类实现特定的行为,确保了子类具有某些必要的功能。
3. 作为类型隐藏和全局变量的角色
在面向对象的方法中,抽象类还可以用来进行类型隐藏和充当全局变量的角色。通过抽象类,开发者可以隐藏具体的实现细节,只对外暴露必要的接口,从而提高了系统的安全性和灵活性。
4. 提供模板方法
抽象类中可以定义模板方法,这些方法提供了算法的框架,但允许子类根据需要实现特定的步骤。模板方法在设计模式中非常常见,它提供了一种标准的方法实现,并允许子类根据实际情况进行定制,从而提高了代码的灵活性和可扩展性。
5. 支持多态性
通过将抽象类作为参数类型或返回类型,可以实现方法的参数多态和返回值多态。这样可以让程序更加灵活,能够处理不同子类对象的统一接口,提高了程序的适应性和可重用性。
6. 捕捉子类的通用特性
抽象类被用来捕捉子类的通用特性,是创建继承层级里子类的模板。它提供了一种方式,让开发者可以定义一组具有共同特征的子类,并通过抽象类来规范这些子类的行为。
7. 促进模块化设计
通过抽象类,开发者可以将系统中的不同部分划分为独立的模块,每个模块都由一个或多个抽象类来定义其接口和行为。这样,系统的结构更加清晰,各个模块之间的耦合度降低,便于开发和维护。