作为一个资深的菜鸡,既然稍微弄通了一点点的继承多态
那当然要写个博客装一下咯吼吼吼吼吼
首先温习一下继承的概念:子类可以继承父类的公有属性和方法并进行重写
public class a extends b{
}
重点1:super和this的使用小解
那么自然而然会想到一个十分哲学的问题:
我想用我父亲的方法该怎么用:
答案是:super函数!
下面简单介绍一下super函数的一个用法:
super函数是唯一一个可以显式调用父类方法:
①构造方法链:构造方法可以调用重载的构造方法。如果父类和子类的构造方法都没有被显式的调用,那么编译器就会自动地将super()作为构造方法的第一句。
public className(){
//some statements
}
等价于
public className(){
super();
//some statements
}
②调用父类方法:super.方法名(参数)
this函数指向类中的属性,也可以指向构造方法;
super和this函数综合
例如:
public class a extends b{
public static void main(String[] args) {
new a();
}
public a(){
System.out.print("invoke a");
}
}
class b extends c{
public b(){
this.b("invoke b");
}
public b(String s){
System.out.print(s);
}
}
class c{
public c(){
System.out.print("invoke c");
}
}
以上程序相当于
public class a extends b{
public static void main(String[] args) {
new a();
}
public a(){
//b的super函数
super();
System.out.print("invoke a");
}
}
class b extends c{
public b(){
//有this的显式调用,不加super函数
this.b("invoke b");
}
public b(String s){
//c的super函数
super();
System.out.print(s);
}
}
class c{
public c(){
System.out.print("invoke c");
}
}
调用顺序即为
a()super → b()this → b()super → c()
重点2:方法重写
方法头不变,方法体可以改写,改写过后可以用super访问父类的未改写的方法;
区分方法重写和方法重载
//方法重写:不改变方法头
public class a {
public String toString(){A;}
}
public class b extends a{
public String toString(){B;}
}
//方法重载,参数列表改变
public void A(double a){}
public void A(int a){}
重点3:多态
概念:每个可以调用父类实例的地方都能调用子类;
Object o = new GeometricObject();
System.out.print(o.toString());
上程序中o调用的是GeometricObject的方法
为什么呢?
上程序中的解释应该是这样的:
创建一个Object类型的引用,指向GeometricObject类型的实例
那也就是:o类型是Object,指向GeometricObject类的实例
这样就会引到动态绑定的问题:
动态绑定工作机制:
假设对象o是类C1,C2,……,Cn-1,Cn的实例,其中C1是C2的子类,C2是C3的子类……Cn是Cn-1的子类,那么就有一个继承串
C1→C2→C3→……→Cn-1→Cn
那么假如o想调用一个方法p,那么JVM会依次在C1,C2……查找方法p,一旦找到并实现后不再继续查找;
例如:
public class Test{
public static void main(String[] args) {
new Person().printPerson;
new Student().printPerson;
}
}
class Student extends Person{
public String getInfo(){
return "Student";
}
}
class Person{
public String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo);
}
}
这个程序的返回是
Person
Student
对第二个的解释:
new Studen().printPerson();
定义后,JVM开始从Student深挖,Student中没有该方法,则调用Person中的该方法,在调用printPerson方法是又需要调用getInfo函数,从Student开始找,在Student中找到,return并输出,程序完成。
对象转换规则和Instanceof函数
对象转换规则:适用于多态的实现
方法:
小转大直接转,大转小强制转
如:
Object o = new Student();
Student b = (Student)o;
(注意转型的语法,比较像数据类型的强制转型)
既然o已经是Student的实例了,为什么还要强制转型?
解释:
小转大直接转的原因是小的总会是大的的子类,因此Student的对象始终也是Object的实例
而大转小时,Object中的实例不一定是Student的实例,因此需要强制转型规定范围;
instanceof函数:判断子类是不是父类的子类
如:
A instanceof B :判断A是不是B的实例,是的话返回true,否的话返回false;
而子类的实例也是父类的实例
所以
A instanceof B返回true
public class A extends C{}
C instanceof B也返回true
暂时到这