如我前面写的技术博客一样,我着重在总结,不会去特别探讨里面的思想:因为思想这东西真是仁者见仁智者见智,关键还是用多了有经验了才能融会贯通,这个基础阶段自己有大致的认识,可以说的通就好。所以关于继承、父子类、多态等应该如何理解思想就不多谈了。
1.格式:class 子类名 extends 父类名{代码}
2.当子类继承了父类后,就具有了父类的功能以及属性。同时由于自己特有的功能和属性,子类会比父类功能更强大。因此,继承的重点是子类如何传承这些功能的。
当成员函数和成员变量不同名的时候是很简单的,也就是这些成员有明确的归属,要么是继承过来的父类的,要么是子类自己的。但当子父类中的成员出现同名的情况时呢,如何确保调用不会混淆出错,有下列规则。
⑴.private修饰的成员就不用多想了,还是只能由父类本身使用,子类访问不了。下面的同名成员都是非私有的。
⑵同名成员变量或函数,其中同名成员函数应做到函数名、参数、返回值都要相同:在子类中调用自己的时,可以用 this.成员名 或直接写成员名,要用到父类的时,则要用 super.成员名 来调用。
这里注意一点:当创建对象后,用对象调用成员时时,只能用 对象名.成员名 来使用子类自己定义的成员,无法再使用super。也就是说:super只能在定义子类时使用,在外界使用子类对象时无法使用。不过可以借助建立方法来间接使用。
简单点就是说:super只能用在子类在定义类的过程中,可以用来使用父类的同名成员。而当子类创建了对象后,用对象调用同名成员时就是自己定义的成员,即所谓的覆盖。
看下面的示例:
public class Test1 {
public static void main(String[] args) {
Zi z1=new Zi(); //创建子类对象
sop(z1.sameH); //调用同名成员变量,不可写z1.super.sameH
z1.fuRun(); //调用同名函数
z1.fuRun2(); //调用父类的特有函数
}
public static void sop(Object obj){
System.out.println(obj);
}
}
class Fu{ //父类
int sameH=1; //定义一个同名成员变量
void fuRun(){ //定义一个同名成员函数
System.out.println("Fu run");
}
void fuRun2(){ //父类特有函数
System.out.println("Fu2 run");
}
}
class Zi extends Fu{ //定义子类继承父类
int sameH=3; //同名成员变量
void fuRun(){ //同名成员函数
super.fuRun(); //调用父类同名函数
System.out.println(super.sameH+" Zi run");
} //调用父类同名成员变量
}
运行结果为
3
Fu run
1 Zi run
Fu2 run
⑶构造函数:子类对象进行初始化时,在所有的构造函数的第一行都有隐式语句super(),即先执行父类的构造函数。
这里有个细节是:隐式语句是super(),是空参构造函数。当父类中没有空参构造函数且子类也没有主动调用父类的有参构造函数时,编译会失败。至于原因,可以这样认为:构造函数是对对象进行初始化的,可能对成员变量或函数有处理动作。子类想继承父类使用成员,就必然要知道这些父类成员经过了哪些初始化处理。否则,便无法继承完整。
示例:将上面代码里的Fu类定义代码里加入
Fu(int i){
sameH=i;
}
将代码再编译,会发现编译无法通过