在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
语法上,在 Java 语言中使用 abstract 关键字 来定义抽象类。示例如下:
abstract class
在 Java 语言中使用 abstract class 来定义抽象类。如下实例:
/* 文件名 : Employee.java */
// 员工类,抽象类
public abstract class Employee {
private String name; // 姓名
private String address; // 地址
private int number; // 工号
// 构造方法,初始化员工信息
public Employee(String name, String address, int number) {
System.out.println("Constructing an Employee"); // 输出构造员工的信息
this.name = name;
this.address = address;
this.number = number;
}
// 计算薪资,抽象方法,具体实现由子类完成
public abstract double computePay();
// 邮寄薪资支票
public void mailCheck() {
System.out.println("Mailing a check to " + this.name + " " + this.address);
}
// 返回员工信息的字符串表示
public String toString() {
return name + " " + address + " " + number;
}
// 获取员工姓名
public String getName() {
return name;
}
// 获取员工地址
public String getAddress() {
return address;
}
// 设置员工地址
public void setAddress(String newAddress) {
address = newAddress;
}
// 获取员工工号
public int getNumber() {
return number;
}
}
注意到该 Employee 类没有什么不同,尽管该类是抽象类,但是它仍然有 3 个成员变量,7 个成员方法和 1 个构造方法。
//AbstractDemo.java 文件代码:
/* 文件名 : AbstractDemo.java */
public class AbstractDemo
{
public static void main(String [] args)
{
/* 以下是不允许的,会引发错误 */
Employee e = new Employee("George W.", "Houston, TX", 43);
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
当你尝试编译 AbstractDemo 类时,会产生如下错误:
Employee.java:46: Employee is abstract; cannot be instantiated
Employee e = new Employee("George W.", "Houston, TX", 43);
^
1 error
抽象类不能实例化对象是指不能使用抽象类本身来创建对象。因为抽象类是一种不完整的类,其中定义了抽象方法但没有提供具体的实现。抽象方法是没有方法体的方法声明,只有方法的签名。由于抽象方法没有具体的实现,因此不能直接创建抽象类的对象。抽象类不能被实例化,也就是说不能通过new关键字来创建对象
原因:
抽象类可以具有构造器的原因是,构造器在创建对象时负责初始化对象的状态。尽管抽象类本身不能被实例化,但它的子类可以被实例化,而构造器的目的是初始化子类的对象。
抽象类中的构造器在子类实例化时起到了重要的作用。当我们创建一个子类的对象时,首先会调用子类的构造器,然后再调用父类的构造器。这是因为子类继承了父类的成员,需要保证父类的状态正确初始化。
**抽象类的构造器与普通类的构造器一样,可以用于为实例变量赋初值、执行其他初始化操作等。**在抽象类的构造器中可以调用抽象类中的非抽象方法,这样可以确保子类在实例化时得到正确的初始状态。
当我们在子类中实现抽象方法时,也可以在子类的构造器中执行一些额外的初始化操作。这样做的好处是,在创建子类对象时,我们可以确保对象在使用之前已经完成了必要的初始化步骤。
举个例子,假设我们有一个抽象类Animal
,其中定义了一个抽象方法makeSound()
和一个非抽象方法eat()
:
abstract class Animal {
public abstract void makeSound();
public void eat() {
System.out.println("The animal is eating.");
}
}
我们希望子类在实例化时能够正确初始化Animal
对象的状态。因此,在子类的构造器中可以调用父类的构造器来完成必要的初始化操作,比如给实例变量赋初值。
class Cat extends Animal {
public Cat() {
super(); // 调用父类的构造器
}
public void makeSound() {
System.out.println("The cat meows.");
}
}
在上面的例子中,子类Cat
继承了抽象类Animal
,并实现了抽象方法makeSound()
。在子类的构造器中,我们调用了父类的构造器super()
来进行初始化。这样在创建Cat
对象时,可以确保Animal
对象的初始化步骤被正确执行。
抽象类可以具有构造器,用来初始化子类对象的状态。在子类的构造器中,可以调用父类的构造器来实现必要的初始化操作。这样可以确保在子类实例化时,对象能够得到正确的初始状态。
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}
继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
如果Salary类继承了Employee类,那么它必须实现computePay()方法:
/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; // Annual salary
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
//其余代码
}
结尾语:记录于2023年8月2号17时33分,以上仅为个人在[Java抽象类—菜鸟教程](Java 抽象类 | 菜鸟教程 (runoob.com))的学习过程中遇到的问题,还有记录的个人想法,有错误欢迎指出,希望对您有帮助,感谢观看!如果可以的话,点点赞,点点关注