在阅读spring源码的时候,发现了一个关于继承的非常有意思的现象,按照常理,在继承链上,子类是完全继承了父类的方法的.那么使用super关键字调用父类的时候,会首先调用到它的直接父类中.但有一种情况,子类没有override父类的某个方法,会导致最底层的类直接调用到它的超类中,我写了一个demo,先来看一下继承图
从继承图中,我们可以看到,儿子继承男人,男人继承人.
接下来我们来定义People类
package com.lazy.demo;
public abstract class People {
//定义了一个age属性
private String age;
//实现get方法
public String getAge() {
return age;
}
//实现set方法
public void setAge(String age) {
this.age = age;
System.out.println("我在People类中setAge");
}
//定义一个具体的run方法
public void run() {
System.out.println("我在People类中跑起来!");
}
//定义一个抽象的say方法,钩子方法
protected abstract void say();
}
定义Man类
package com.lazy.demo;
public class Man extends People {
@Override
//重写父类的run方法
public void run() {
System.out.println("我先进入到了Man类中");
super.run();
}
@Override
//重写父类的say方法
protected void say() {
System.out.println("我在Man类中说: 我29岁了!");
}
//未重写父类的age属相的get与set方法
}
定义Son类
package com.lazy.demo;
public class Son extends Man {
@Override
//重写父类的say方法
protected void say() {
super.say();
}
//定义一个setAge方法,在方法体内通过super关键字想调用父类的setAge方法
public void setAge() {
super.setAge("29");
}
//定义一个run方法,在方法体内通过super关键字调用父类的run方法
public void run() {
super.run();
}
}
测试1,测试Son类中的setAge方法
package com.lazy.demo;
public class Test {
public static void main(String[] args) {
//实例化Son对象
Son son = new Son();
//通过Son对象的引用son,调用Son中定义的setAge方法
son.setAge();
}
}
运行结果
看到这个现象,有趣吧!在Son类的父类Man类中,我们并没有重写People类中的setAge方法,但是在Son类中,我们通过super关键字,居然不是调用到父类中,而是调用到了超类(People)的setAge方法中.当然,这只是个小知识点,不足为奇,在spring的源码中,就有这种写法,读懂这个小程序,能为我们读spring的源码省下一些气力. so,路要一步一步走,饭要一口一口吃.只有掌握了扎实的基础,才能让自己的内功大增.
测试2,测试Son类中的run方法
package com.lazy.demo;
public class Test {
public static void main(String[] args) {
//实例化Son对象
Son son = new Son();
//通过Son对象的引用son,调用Son中定义的run方法
son.run();
}
}
运行结果
由于Man类中重写了People类中的run方法,所以在Son类中run方法中,通过super关键字调用父类的run方法,会首先调用的Man类中的run方法,Man类中的run方法又通过关键字调用到People类中的run方法,这不足为奇,符合我们的预期.
测试3.测试Son类中的say方法
package com.lazy.demo;
public class Test {
public static void main(String[] args) {
//实例化Son对象
Son son = new Son();
//通过Son对象的引用son,调用Son中定义的say方法
son.say();
}
}
运行结果
Man类中,我们重写了People类中的say方法,但是在People类中的say方法体中,并没有通过super关键字在往上调用People类中的say方法,而且在People类中的say方法是一个抽象方法,我们也不可以通过关键字去调用,否则编译器都会报错.所以,在Son类中的say方法中,只可通过super关键字调用到在People类中定义的抽象方法say方法的实现类,也就是Son类的直接父类.
小结:
1.通过以上例子,我们看到了面向对象的精华--多肽的一些影子
2.类可以被单继承,但可以不重写某些方法,这样一来,在子类中,通过关键字super调用父类的方法,会直接进入到超类中
3.public protected方法,可以层层继承下来,也可以在底层通过super关键字,层层调用上去