一、抽象类的基本概念
1、什么是抽象类
在面向对象编程中,所有的事物都可以看做为对象,所有的对象都是通过类来描绘的,但并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类与普通类除了不能实例化对象以外,类的其他功能依旧存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类并不能实例化对象,所有抽象类必须被继承才能被使用。
抽象类的特点
- 使用abstract修饰
- 抽象类不可以实例化对象
- 抽象类可以包含抽象方法和普通方法
2、什么是抽象方法
在特定情况下,需要一个特别的成员方法,该方法的具体事项由它的子类确定,那么在父类中声明该方法为抽象方法。
抽象方法没有方法体,只有一个方法名,并且用abstract声明。
抽象方法的特点
- 使用abstract修饰符
- 抽象方法没有方法体
- 抽象方法必须定义在抽象类当中
- 父类当中的抽象方法要求子类必须强制重写,除非子类也是抽象类
示例
package com.entity;
public abstract class Pet { //定义抽象类Pet
private String name; //封装属性
private int age;
//添加get/set访问器(提供读取,写入)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//添加无参构造
public Pet(){}
//有参构造
public Pet(String name, int age) {
this.name = name;
this.age = age;
}
//定义普通方法
public void print(){
System.out.println(this.name+this.age);
}
//定义抽象方法
public abstract void text();
}
package com.entity;
public class Text {
public static void main(String[] args) {
//强制创建 抽象类 的对象
Pet pet=new Pet();
pet.print();
}
}
编译运行后
Information:java: Errors occurred while compiling module 'Mode'
Information:javac 13 was used to compile java sources
Information:2020/6/6 23:22 - Build completed with 1 error and 0 warnings in 4 s 806 ms
F:\JavaIDE\src\com\entity\Text.java
Error:(5, 17) java: com.entity.Pet是抽象的; 无法实例化
由此可见,当一个类为抽象类时,无法直接进行实例化操作。
原因:当一个类示例化后,就意味着这个对象就可以调用类中的属性或者方法了,但在抽象类中存在抽象方法,抽象方法没有方法体,没有方法体就无法进行调用,既然无法调用,又怎么能产生实例化对象呢。
抽象类的使用原则如下:
- 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
- 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
- 抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
- 子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。)
二、抽象类的继承
1、什么是继承
继承就是子类继承父类的特征和行为,使子类对象具有父类的属性和方法,从而具有父类相同的行为
2、为什么要继承
减少代码重复率 提高代码的重用性
3、继承的用法
将子类共有的属性和方法定义在父类当中,在子类当中只保留特有的属性方法
4、继承的实现方式
案例
package com.entity;
public abstract class Pet { //定义抽象类Pet
private String name; //封装属性
private int age;
//添加get/set访问器(提供读取,写入)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//添加无参构造
public Pet(){}
//有参构造
public Pet(String name, int age) {
this.name = name;
this.age = age;
}
//定义普通方法
public void print(){
System.out.println(this.name+this.age);
}
//定义抽象方法
public abstract void text();
}
package com.entity;
//Pet抽象类的子类Dog
public class Dog extends Pet {
//重写抽象方法 强制重写
@Override
public void text() {
System.out.println("名字:"+this.getName()+"\n年龄:"+this.getAge());
}
}
package com.entity;
public class Text {
public static void main(String[] args) {
Pet pet=new Dog();//向上转型
pet.setName("贝贝");
pet.setAge(5);
pet.text();//被子类Dog所重写的方法
}
}
运行结果
名字:贝贝
年龄:5
方法重写:子类改造父类当中已经存在的方法
方法重写的特点:
- 同名
- 同参
- 不同类
- 返回值相同
- 权限不可以缩小
方法的重写规则
参数列表必须完全与被重写方法的相同。
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
父类的成员方法只能被它的子类重写。
声明为 final 的方法不能被重写。
声明为 static 的方法不能被重写,但是能够被再次声明。
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
构造方法不能被重写。
如果不能继承一个方法,则不能重写这个方法。