前面学习过,面向对象程序设计的基本原则有四个,即抽象原则、封装原则、继承原则、多态原则。
今天来学习一下第三个基本原则——继承原则。
一、继承概念
继承原则的主要作用就是代码复用,降低编码量。
在Java中,有extends这样一个关键字负责继承的模块,表示一个类继承了某一个父类。
比如先定义一个User类,代表人类
public class User { private String name; private int age; // ...省略get set方法 }
再定义一个学生类继承User类
public class Student extends User{ }
此时,学生类就包括了User类的变量,可以在测试类调用
public class Main { public static void main(String[] args) { Student student = new Student(); student.setName("张三"); student.setAge(18); } }
在Student类并没有定义成员变量,但存在两个父类的成员变量,这就是继承!
二、访问级别
public class User { // private 级别 private String name1; // 默认 级别 String name2; // protected 级别 protected String name3; // public 级别 public String name4; }
访问权限明细如下
访问权限 | 类内部 | 包下的类 | 非本包子类 | 非本包非子类 |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
默认 | √ | √ | × | × |
private | √ | × | × | × |
java.lang.Object类是所有Java类的超类,即所有Java类都直接或者简介继承了java.lang.Object类。
在Object类中,定义了Java对象都应具备的方法。
即使某一个类没有使用extends关键字,也默认直接继承了Object类,这是Java的约定。
比如User类
public class User { // private 级别 private String name1; // 默认 级别 String name2; // protected 级别 protected String name3; // public 级别 public String name4; }
等同于
public class User extends Object{ // private 级别 private String name1; // 默认 级别 String name2; // protected 级别 protected String name3; // public 级别 public String name4; }
三、super关键字
之前学习了this关键字,this代表着当前对象本身。
在Java的继承关系中,子类也需要去调用父类的资源,Java提供了super关键字来实现这类功能。
super还可以调用被覆盖或者被隐藏的父类方法。
父类User定义了say方法
public class User{ public void say() { System.out.println("我是User类"); } }
子类Student也定义say方法
public class Student extends User{ @Override public void say() { System.out.println("我是Student类"); super.say(); } }
在测试类中,调用Student方法
public class Main { public static void main(String[] args) { new Student().say(); } }
输出如下,即子类Student调用了父类User的say方法
我是Student类 我是User类 Process finished with exit code 0
在实际编程中,一般在类的构造方法中,或者调用父类被覆盖/隐藏方法的场景下会用到super关键字。
四、方法覆盖
方法覆盖即方法重写,至子类存在和父类同名同参同返回类型的方法,覆盖掉了父类的方法,即子类重写父类继承下的方法,给出新的执行代码。
之前介绍的User和Student的say方法就是方法覆盖的demo。
五、属性隐藏
属性隐藏指在子类重新定义了父类同名的成员变量,从而导致在子类中不能找到父类继承而来的成员变量。
子类可以通过属性隐藏,来实现父类未完善的功能,对父类的功能进行进一步扩展。
public class User{ public String post; }
public class Student extends User{ public String post = "学生"; }
public class Main { public static void main(String[] args) { System.out.println(new Student().post); } }
输出
学生 Process finished with exit code 0
但继承不是万能的,父类的构造方法不能被继承,private的私有成员变量/方法也不能被继承,子类覆盖方法的访问权限不能比父类低,不能修改父类方法的是否静态属性。
六、方法重载
前面学习的方法覆盖,指的是Java继承关系中,子类对父类继承而来的方法进行了重写,存在于不同的类中,要求子类的方法声明和父类一致。
而方法重载指的是同一个类中有多个同名的方法,但方法的参数、返回类型至少有一个不同,且方法的代码也不一样,要求子类的方法声明和父类不完全一致。
如下面的add方法
public class Main { public static int add(int x,int y) { return x + y; } public static float add(float x,float y) { return x + y; } public static float add(int x,float y) { return x + y; } public static void main(String[] args) { System.out.println(add(1, 2)); } }
add方法当Java程序编译时,就能动态调用哪一个方法,而方法覆盖只有当Java程序运行时,才能唯一确定调用哪个方法。
idea工具会给与调用提示
七、final关键字
在实际开发中,父类只允许子类继承,但不允许子类修改。
在一些安全性较高的场景下会有这样一个需求。
此时可以将父类方法或父类成员变量增加final关键字修饰,子类将不能更改父类的成员方法。
public class User{ public final void say() { System.out.println("我是USER"); } }
子类无法重写覆盖
预告:下一篇计划学习Java接口