众所周知Java面向对象语言有三大特点,封装性,继承性和多态性,其中继承性是多态性的基础,下面我们来简单分析一下其中的继承性。
我们知道,在开发Java程序时,jdk当中为我们提供好了许多可直接利用的类.而在某些情况下,现成提供的类中的方法有时无法满足我们的需要,但同时我们又要用到其中的某些方法,这个时候利用Java的继承性就显得十分方便。总体来说继承性解决的主要问题就是共性抽取。但需要注意的时Java语言是单继承的,但可以多级继承,也可以一个父类有多个子类,但绝不可以一个子类有多个父类,即一个类的直接父类只能由一个,父类往上可以还有父类,直到Java.lang.object类,它是所有类的父类,如果一个类没有特别指定父类,那么默认则继承自object类。下图比较直观的反应了Java当中的继承关系
下面我们再从以下三个方面来具体的分析:
1.方法的覆盖(重写override)
继承关系中,方法名称一样,参数列表也一样,这时候就会产生方法的重写。在继承中我们主要进行的就是从已有的类创建新类的过程,对于已经投入使用的类,我们尽量不要对其进行修改,最好是定义一个新的类,来继承的同时再在其中定义新的方法。在进行方法重写时,我们有两个硬性规定和一个软性建议,首先子类方法的返回值必须小于等于父类方法返回值的范围(eg:object>string),其次子类方法的权限必须大于等于父类方法的权限(eg:public>protect>留空>private)。最后建议将@override写在方法前面用来检测是不是方法重写。
eg1:
//创建了一个父类
public class Fu{
protect object method(){ //父类的返回值范围大于子类,但访问权限小于子类
return null ;
}
}
//创建了一个子类方法,继承父类
public class Zi extends Fu{
@override
public String method(){ //访问权限:public>protect,返回值范围:object>string
return null ;
}
}
eg2:
我们以现实生活中的手机为例,老手机中有打电话,发短信,来电显示(但只显示号码)的功能,在更新换代时,发行的新版手机继承老手机功能的同时,又在来电显示上增加了显示姓名与头像的功能
/*定义一个老手机类,有打电话,发短信,来电显示的方法,但其中来电显示只能显示
*号码
*/
public class Phone{
public void call(){
System.out.println("打电话!");
}
public void send(){
System.out.println("发短信!");
}
public void show(){
System.out.println("显示号码!");
}
}
/*定义一个新手机类,继承打电话,发短信功能的同时,在来电显示上增加显示号码和
*头像的功能
*/
public class NewPhone extends Phone{
@override //检测是否为方法重写
public void show(){
super.show(); //继承父类的show方法
System.out.println("显示姓名!");
System.out.println("显示头像!");
}
}
public class DemoExtend{
public static void main(String args[]){
NewPhone newphone = new NewPhone(); //创建一个新款手机对象
newphone.call();
newphone.send();
new.show(); //显然继承的同时又有新功能的出现
}
}
2.super与this关键字
super关键字常见的三种用法:第一在子类成员方法中访问父类成员变量,第二在子类成员方法中访问父类成员方法,第三在子类构造方法中访问父类构造方法总的来说super就是用来子类用来访问父类内容的。而this关键自字则恰恰与其相反是用来访问子类本身内容的,同样的它的三种常见的用法为:第一在本类方法中,访问本类的成员变量。第二在本类的成员方法中,访问本类的另一个成员方法。第三,在本类的构造方法中访问奔类的另一个构造方法。
eg3:
用super,this区分重名的成员变量名。
//定义一个父类
public class Fu{
int num=10; //父类当中的成员变量
}
//定义一个子类
public class Zi extends Fu{
int num=20; //子类当中的成员变量
public void method(){
int num=30;
System.out.println(num); //局部变量
System.out.println(this.num); //本类的成员变量
System.out.println(super.num); //父类的成员变量
}
}
public class DemoExtend{
public static void mian(String args[]){
Zi zi = new Zi();
zi.method();
}
}
3.继承当中的访问规则
eg4:
在父子类继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:第一直接通过子类对象访问成员变量,即创建的对象是谁,就优先用谁,没有则往上找。第二间接通过成员方法访问成员变量,即该方法属于谁,就优先用谁。
//定义一个父类
public class Fu{
public void methodFu(){
System.out.println("父类成员方法执行!");
}
public void method(){
System.out.println("父类重名方法执行!");
}
}
//定义一个子类继承父类,并且定义一个与父类重名的成员方法
public class Zi extends Fu{
public void mathodZi(){
System.out.println("子类成员方法执行!");
}
public void method(){ //此方法与父类重名
System.out.println("子类重名方法执行!");
}
}
public class DemoExtend{
public static void main (String args[]){
Zi zi = new Zi(); //创建一个子类对象
zi.method(); //由于创建的是子类对象所以优先使用子类方法
//没有则往上找
}
}
eg5:
在父子继承关系中访问构造方法的规则:第一先调用父类构造,后执行子类构造,因为子类构造方法当中有一个隐含默认的“super();”调用,子类必须调用父类构造方法,不写则“赠送”super();语句,如果写了则用写了的。第二super的父类构造调用必须是子类构造方法的第一个语句,不能一个子类多次调用super构造。第三子类可以通过super关键字来调用父类的重载构造。
//创建一个父类
public class Fu{
public fu(){
System.out.println("父类无参构造方法!");
}
public fu(int num){ //定义一个全参数的构造方法
System.out.println("父类全参数构造!");
}
}
//创建一个子类继承父类
public class Zi extends Fu{
public zi(){
//super(); 此语句不写则隐含,默认调用无参构造
//super(20);若写此语句则发生重载,调用父类有参构造
//但必须注意的是以上这两个语句有且仅有一个
System.out.println("子类构造方法!");
}
}
public class Demoextend{
public static void main(String args[]){
Zi zi = new Zi();
/*这个时候如果运行程序,会显示父类构造方法,后显示子类构造方法,
*因为子类构造方法中有一个隐含的super();调用。
*/
}
}
以上即是对java当中继承性的简单概述。