目录
7.java继承的三个特点
(1)java只支持单继承,即一个类的直接父类只能有一个。
(2)java支持多级继承,即子类也可以被当做父类被其他类继承。java中最高层次的父类是java.lang.Object类,所有类都直接或间接的继承了这个类。
(3)一个子类的直接父类是唯一的,一个父类可以拥有多个子类。
8.抽象类与抽象方法
(1)问题提出
如图所示,我们定义一个图形类,那么对任意图形,都有一个求面积的方法,但是不同图形的面积求法不一样,因此无法在父类中定义一个具体的求图形面积的方法。因此在这里引入抽象方法,在父类中只是指明每个子类都要继承这个方法,然后在子类中具体描述这个方法。
(2)定义
抽象类:只在普通类的基础上扩充了一些抽象方法
抽象方法:只声明而未实现的实体(即抽象方法没有方法体)
(3)格式
①首先定义一个图形的抽象类,并给它求面积的抽象方法。三角形类继承这个抽象类,并重写父类所有抽象方法。
//具有抽象方法的类必须为抽象类
public abstract class Figure {
//抽象方法只需要给定方法的基本信息(返回值,方法名,参数信息)
//但不写方法体,方法具体步骤在子类中实现
public abstract double area(double a,double b);
}
//三角形
public class Triangle extends Figure {
//传入参数为底和高
public double area(double a, double b) {
return a * b / 2;//底乘高除以二
}
}
②创建实例并打印结果。
public static void main(String[] args){
Triangle triangle = new Triangle();
double result = triangle.area(3,4);
System.out.println(result);
}
结果:6.0
(4)注意事项
①抽象类不能直接实例化(创建对象)。
②抽象类除抽象方法外其他属性和方法以及构造方法的继承与普通类的继承完全一样。
③抽象类中不一定包含抽象方法,但有抽象方法的类一定是抽象类。
④抽象类的子类必须重写抽象类的所有抽象方法,否则报错。
9.java中的接口(interface)
(1)接口的定义
接口是一种特殊的继承关系,它主要是为了解决以下两个问题:
①我们在java中定义大量的同一个类型的不同类,而这些类的使用方法也不尽相同,那么如何统一这些类的使用方法。(比如所有的USB设备都用USB接口,实现数据传输,即公共的规范标准)
②java只支持单继承,那么一个类既想要继承多个父类特性该如何实现。
(2)接口的创建和实现
①首先我们定义一个接口
//接口类不用class,而用interface
//Java8以前接口中只能含有常量和抽象方法
public interface Father {
//接口中的常量必须由public static final修饰,且可以省略
//接口中的常量一旦定义赋值就不可修改
//使用时为接口名.变量名
public static final int a = 10;
//接口中的方法必须为抽象方法,且方法修饰符必须为 public abstract
public abstract void fun1();
//public abstract可以省略,但绝对不可改变
public void fun2();//省略abstract(常见格式)
abstract void fun3();//省略public
void fun4();//省略
}
②实现上面这个接口。注意到无论有多少个类实现上面的接口,他们关于这个接口的使用方法都完全一致,只是方法体不同而已,这样就解决了第一个问题。
//实现(继承)接口必须重写接口所有的方法(所有方法均为抽象方法)
//实现接口用implements而不用extends
public class Son implements Father{
@Override
public void fun1() {
System.out.println("方法1");
}
@Override
public void fun2() {
System.out.println("方法2");
}
@Override
public void fun3() {
System.out.println("方法3");
}
@Override
public void fun4() {
System.out.println("方法4");
}
}
③下面我们再定义一个接口。
public interface Mother{
public void motherFun1();
public void motherFun2();
}
④仍用Son实现Mother接口。我们发现Son能够同时实现Father接口和Mother接口,这就解决了第二个问题。
public class Son implements Father,Mother{
@Override
public void fun1() {
System.out.println("方法1");
}
@Override
public void fun2() {
System.out.println("方法2");
}
@Override
public void fun3() {
System.out.println("方法3");
}
@Override
public void fun4() {
System.out.println("方法4");
}
@Override
public void motherFun1() {
}
@Override
public void motherFun2() {
}
}
(3)不同的版本对接口的改进
①Java7:只有常量,抽象方法。
②Java8:新增了默认方法和静态方法。
//接口
public interface Mother {
public void motherFun1();
public void motherFun2();
//默认方法:主要是为了解决接口升级的问题
//同一个方法不同的版本内容不同,如果都用抽象方法,同一个方法实现时必须实现所有版本的方法
//我们把经常多个版本的的方法写成默认方法,使用时直接调用即可,也可根据需求在实现类中重写
public default void defaultMethod() {
//方法体
System.out.println("这是默认方法");
}
//静态方法:直接针对接口的方法
//使用时直接通过接口名.方法名调用
public static void staticMethod() {
//方法体
System.out.println("这是静态方法");
}
}
//实现类
public class MotherImpl implements Mother {
@Override
public void motherFun1() {
System.out.println("抽象方法1");
}
@Override
public void motherFun2() {
System.out.println("抽象方法2");
}
@Override
public void defaultMethod() {
System.out.println("重写了默认方法");
}
}
③Java9:新增了私有方法,用来解决默认方法和静态方法中提取重复代码但又不想让用户调用的问题。
public default void defaultMethod() {
//方法体
System.out.println("这是默认方法");
def();
}
//静态方法
public static void staticMethod() {
//方法体
System.out.println("这是静态方法");
sta();
}
//默认方法的私有方法
private void def(){
//重复代码
}
//静态方法的私有方法
private static void sta(){
//重复代码
}
(4)接口的使用
public class Start {
public static void main(String[] args) {
//使用(静态)常量时接口和实现类所指向的是同一个常量
System.out.println(Father.a);
System.out.println(Son.a);
//使用接口静态方法,只能由接口调用,不能由实现类调用
Mother.staticMethod();
//创建一个接口实现类
Mother mother = new MotherImpl();
mother.defaultMethod();//接口的默认方法(被实现类重写)
mother.motherFun1();//抽象方法
}
}
结果为:
10
10
这是静态方法
重写了默认方法
抽象方法1
10.继承父类并实现多个接口时的注意事项
public class SonImpl extends People implements Mother,Father
(1)接口是没有静态代码块或者构造方法的。
(2)一个类只能继承一个父类,但是可以实现多个接口。
(3)如果实现类所实现的多个接口有重复(除方法体外完全一样)的抽象方法,只需要重写一次即可。
(4)如果实现类所实现的多个接口有重复的默认方法,实现类要重写默认方法。
(5)如果实现类不想重写所实现接口的所有抽象方法,那么实现类必须为抽象类,且必须通过被子类继承实现。
(6)若子类所要继承的父类方法与接口中的默认方法冲突,优先使用父类方法(继承先于接口,重写先于所有)。
11.接口之间的多继承 —— 接口可以多继承
public interface InterfaceA {
public void methodA();
public void common();//重复的抽象方法
public default void defaultMethod(){
System.out.println("A的默认方法");
}
}
public interface InterfaceB {
public void methodB();
public void common();//重复的抽象方法
public default void defaultMethod(){
System.out.println("B的默认方法");
}
}
//子类接口
public interface InterfaceC extends InterfaceA,InterfaceB {
public void methodA();
public void methodB();
public void common();//抽象方法不会冲突,会在实现类中重写
//冲突的默认方法必须重写,重写后仍是默认方法
@Override
default void defaultMethod() {
//重写方法体
}
}
此处注意:若要在子接口中实现父接口的抽象方法,则实现的方法均为默认方法。