抽象类和接口
抽象类
abstract被用于声明抽象的关键字
- 抽象类中包含的成员与普通类包含的相同,抽象类还可以多包含一种抽象方法。
- 抽象类不能被实例化,它所包含的构造器主要被用于子类调用。
归纳:抽象方法有得有失,比普通类多了一种抽象方法,比普通类少了一种被实例化的能力。
- 抽象方法
- 被abstract修饰的方法,没有方法体
示例:public abstract void fun();
一个类继承了抽象类以后,那么这个类必须去实现(重写)抽象类中的所用抽象方法,如果子类也是抽象类那么可以声明那个抽象方法,否则必须要去实现这个抽象方法。
抽象类必须被继承才有意义,所以abstract和final不能同时修饰一个类。
- 抽象类的作用
- 从多个具体相同特征的类中抽象出一个抽象类,以它作为子类的模板,从而避免子类设计的随机性。
- 如果抽象类中的一个方法依赖一个抽象方法,这个方法会被推迟到子类去实现。
import java.util.*;
abstract class Volume {
private int number;
public Volume() {
Scanner in = new Scanner(System.in);
this.number = in.nextInt();
}
public abstract double onlyOne();//计算一个长方体的体积的抽象方法
public double getValue() {
return onlyOne() * number;//这个会推迟到子类中去实现
}
}
class Cuboid extends Volume {
private double length;
private double width;
private double height;
public Cuboid(double length, double width, double height) {
this.length = length;
this.width = width;
this.height = height;
}
//重写实现抽象方法
@Override
public double onlyOne() {
return length * width * height;
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Cuboid a = new Cuboid(in.nextDouble(), in.nextDouble(), in.nextDouble());
System.out.println(a.getValue());
}
}
接口
接口定义的是一种规范,如果一个类去实现某个接口那么这个类必须要符合它定义的规范
接口体现的是一种规范和设计分离的哲学
接口定义不再使用class关键词,而是用interface关键词表示接口
接口的访问权限public或者default(默认)
接口可以多继承接口但是不能继承类
不能定义 | 构造器、初始化块 |
---|---|
都是默认public访问权限 | 就算没写系统也会== 为所有接口成员默认添加public== |
变量 | 静态常量 (public static final) |
方法 | 抽象方法、类方法、默认方法、私有方法(java9) |
内部类 | 内部接口、枚举 (都采用public static,默认就会添加public static) |
- 定义方法的时候如果不是定义类方法、默认方法、私有方法,系统会自动为普通方法增加abstract修饰符
- 其中私用方法不会自动是个特殊,它不会被自动加上public
- 默认方法其实就是一种实例方法,但是因为接口中实例方法会被自动添加abstract修饰符,所以java8引进默认方法表示实例方法(这里的default并不表示访问权限)
public default void fun() {方法体}
接口可以当成一种特殊的类,所以一个java文件中只能定义一个public的接口并且java文件名要和public的接口名相同
- 接口不能创建实例,但是接口可以用来声明引用类型变量。当使用接口来声明引用类型变量时,这个引用类型变量必须引用到 其他实现类的对象(接口用途之一)
- 实现接口可以理解成一种特殊的继承(继承了一个彻底的抽象类)
- 类来实现接口的时候用关键字implements并且必须位于extends的后面
- 接口的抽象方法必须全部实现,除非是一个抽象类去实现这个接口,那么不需要实现的抽象方法可以在这个类中被声明成抽象方法
抽象类和接口可以用来当做编译时类型(利用多态)
抽象类的运行时变量:实现抽象类的子类。
接口的运行时变量:实现接口的实现类。
补充
1.extends:类与类之间(包括抽象类)
2.implements:接口与类之间的关系
3.父类实现了某个接口那么子类也会去实现那个接口
如果父类是一个普通类那么父类就重写接口方法子类继承以后就不用再去重写
如果父类是一个抽象类那么父类可以继承接口的方法留给子类去重写
通过instanceof可以知道子类其实也是父类实现的那个接口的一个实现类,同样可以向上造型为接口类型