清楚了继承的基本概念,此时就可能出现一种情况,如果子类定义了父类相同的方法或属性,这就成为覆写。
方法的覆写
方法的覆写是子类定义了与父类方法名称、参数类型及个数完全相同的方法,但是被覆写的方法不能够拥有比父类更为严格的访问控制权限。
范例: 简单的方法覆写
class Person {
public void printInfo() {
System.out.println("【Person类】printInfo()方法");
}
}
class Student extends Person {
public void printInfo() {
System.out.println("【Student类】printInfo()方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.printInfo();
}
}
进行覆写方法使用的时候得注意两点:
- 当前使用的对象是通过那个类
new
出来的 - 当调用某一个方法,如果该方法已经被子类覆写了,则调用的一定是子类中覆写的方法。
在进行方法的覆写的时候也有一个明确的要求:被覆写的方法不能够拥有比父类更为严格的访问控制权限,private < default < pubic
。
那么也意味着如果父类中方法使用了public
进行定义,那么子类中使用的权限只能是public
,而如果父类中使用的是default
权限,子类可以使用default
或者public
。方法一般也是public
修饰的。属性基本用private
修饰。
范例: 父类的方法使用private
定义,子类同名方法使用public
定义。
class Person {
public void fun() {
this.printInfo();
}
//如果现在父类中的方法使用了private定义,那么就表示该方法只能被父类所使用,
//子类无法使用,也就是子类根本不知道父类有这样的方法。
private void printInfo() {
System.out.println("【Person类】printInfo()方法");
}
}
class Student extends Person {
//这个时候该方法只是子类定义的新方法而已
//跟父类重名的方法没关系
public void printInfo() {
System.out.println("【Student类】printInfo()方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.fun();
}
}
例子: 重载与覆写的区别
No | 区别 | 重载(Overload) | 覆写(Overwrite) |
---|---|---|---|
1 | 概念 | 方法名称,参数的类型和个数不同 | 方法名称、返回值类型、参数的类型和个数完全相同 |
2 | 范围 | 发生在一个类之中 | 发生在继承关系之中 |
3 | 限制 | 没有权限要求 | 被覆写的方法不能拥有比父类更为严格的方位权限 |
方法重载的时候返回值可以不同,但是良好的设计上要求返回类型一致。
属性覆盖
当子类定义了和父类属性完全相同的属性的时候就是属性覆盖。
class Person {
public String info = "mrbacker";
}
class Student extends Person {
public int info = 100; //属性名称相同
public void printInfo() {
//按照就近取用的原则,取的是被覆盖的属性名称
System.out.println(info);
}
}
public class TestDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.printInfo();
}
}
这种操作本身是没有意义的,其核心的原因在于:所有类中的属性都要求使用private
封装,那么一旦封装了,子类不知道父类的private
属性,覆盖属性也就没有意义了,所以尽量不使用同名的属性。
super关键字
子类实例化的时候出现的super()的形式,其主要作用是由子类调用父类构造方法,进行覆写的操作过程之中,子类也可以使用super.方法()
、super.属性
明确地调用父类中的方法或属性。
范例: 观察一下程序
class Person {
public void printInfo() {
System.out.println("1111");
}
}
class Student extends Person {
public void printInfo() {
super.printInfo();
System.out.println("2222");
}
}
public class TestDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.printInfo();
}
}
如果此时写上了this.printInfo()
操作,那么就表示先从本类查找所需要的方法,如果本类没有,则去找父类中指定的方法进行调用。如果是super.printInfo()
表示的是不查找本类而调用父类中的方法。
范例: 观察调用父类属性
class Person {
public String info = "mrbacker";
}
class Student extends Person {
public int info = 100; //属性名称相同
public void printInfo() {
//不查找本类的属相,直接查找父类中的属性
System.out.println(super.info);
System.out.println(info);
}
}
public class TestDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.printInfo();
}
}
发现super和this使用形式上非常相似,但是最大的区别在于super是子类访问父类的操作,而this是本类的访问操作。
No | 区别 | this | super |
---|---|---|---|
1 | 概念 | 访问本类中的属性、方法 | 由子类访问父类中的属性、方法 |
2 | 查找范围 | 先查本类,如果本类没有则调用父类 | 不查找本类而直接调用父类定义 |
3 | 特殊 | 表示当前对象 | 无 |
能使用super.方法()
一定要明确标记出是父类的操作。
总结
- 子类覆写父类的方法是因为父类的方法功能不足,才需要覆写;
- 方法覆写的时候使用的是public权限,方法名字复制粘贴。