首页 > 代码库 > 面向对象三大特征——继承
面向对象三大特征——继承
继承 :子类继承父类,子类将得到父类的全部方法和Field,但不能获得父类的构造器,一个子类只有一个直接的父类,用 extends 关键字来实现。
1、子类将得到父类的全部方法 ,不代表子类对象可以访问所有父类方法。分三种情况:
a、父类方法用private修饰,子类对象将无法访问该方法。
b、父类方法与子类方法同名(方法名、形参名),子类方法将覆盖父类方法(或者叫重写),子类对象将无法直接访问该方法。但可以间接访问,这里就要用到super关键字或父类名来访问了,具体下面再讨论。
c、除去上面2种情况,子类对象才能直接访问父类方法。
1 class BaseClass 2 { 3 private void test(){ 4 System.out.println("父类test方法"); 5 } 6 public void base(){ 7 System.out.println("父类base方法"); 8 } 9 void kass(){10 System.out.println("父类的kass方法");11 }12 }13 public class SubClass extends BaseClass14 {15 public void kass(){16 System.out.println("子类的kass方法");17 }18 public static void main(String[] args){19 SubClass bc = new SubClass();20 //bc.test(); //因父类test方法设值了private权限,故这里无法访问。21 bc.kass(); //方法相同,子类覆盖父类方法,这里只能访问子类方法。22 bc.base(); // 正常访问父类base方法。23 }24 }
这里还要就子类重写父类方法说明几点:
1、方法名相同、形参列表相同。如果子、父类都用private修饰符,子类依旧不能访问父类方法。
2、子类方法返回值类型应比父类更小或相等,子类方法声明抛出的异常类应比父类更小或相等。
3、子类方法的访问权限应比父类更大或相等。权限从小到大:省略修饰符<protected<public 。
4、方法覆盖的子、父类方法要么都是类方法,要么都是实例方法。也就是要么都用static修饰,要么都不用。
关于子类对象调用父类被覆盖的方法:
1、类方法:通过 父类类名.方法名(形参列表); 来访问。
2、实例方法:通过 super.方法名(形参列表);来访问。
说明:只能在子类方法中通过父类类名或super来调用父类被覆盖的方法。
1 class BaseClass 2 { 3 static void test(){ 4 System.out.println("父类test方法"); 5 } 6 public void kass(){ 7 System.out.println("父类的kass方法"); 8 } 9 }10 public class SubClass extends BaseClass11 {12 static void test(){13 System.out.println("子类test方法");14 BaseClass.test(); //调用父类test方法15 }16 public void kass(){17 System.out.println("子类的kass方法");18 super.kass(); //调用父类kass方法19 }20 public static void main(String[] args){21 SubClass bc = new SubClass();22 bc.test();23 bc.kass();24 }25 }
2、子类将得到父类的全部Field ,不代表子类对象可以访问父类所有Field。分三种情况:
a、父类Field用private修饰,子类对象将无法访问该Field。
b、父类Field与子类Field同名,子类Field将隐藏父类Field,子类对象将无法直接访问父类Field。但可以间接访问,这里就要用到super关键字或父类名来访问了,具体下面再讨论。为什么叫隐藏,因为子类创建对象时依然为父类Feild分配内存空间。
c、除去上面2种情况,子类对象才能直接访问父类Field。
1 class BaseClass 2 { 3 static int a = 5; 4 public int b = 8; 5 private int c = 11; 6 } 7 public class SubClass extends BaseClass 8 { 9 static int a = 5;10 public int b = 8;11 private int c = 11;12 public void test(){13 System.out.println(super.b);//super只能放在非静态方法中14 System.out.println(super.c);//子类中无法访问父类private修饰的Field,故会报错15 }16 public static void main(String[] args){17 SubClass bc = new SubClass();18 System.out.println(BaseClass.a); //静态修饰的Field用父类名.Field名 调用19 bc.test();20 }21 }
说明:如果在子类某个方法中访问名为a的Feild,但没有super或父类名调用,则系统查找a的顺序是:
1、查到当前方法是否有名为a的局部变量。
2、查找当前类是否有名为a的Feild。
3、查找父类中是否包含名为a的Feild,依次上溯a的所有父类,直到java.lang.Object类,最终找不到将出现编译错误。
3、不能获得父类的构造器,但可以调用父类构造器的初始化代码
在一个构造器调用另一个重载的构造器使用this调用来完成,在子类构造器中调用父类构造器使用super调用来完成,super调用必须在构造器代码首行。
不管是否用super来调用父类构造器初始化代码,子类构造器总会调用父类构造器一次,如果父类构造器是无参构造器,将不会输出任何信息。
创建任何对象总是从该类所在继承树最顶层类的构造器开始执行,然后依次向下执行,最后才到本类构造器。
1 class BaseClass 2 { 3 public int a; 4 public String b; 5 public BaseClass(int a,String b){ 6 this.a = a; 7 this.b = b; 8 } 9 }10 public class SubClass extends BaseClass11 {12 public double c;13 public SubClass(int a,String b,double c){14 super(a,b); //通过super调用父类构造器初始化过程15 this.c = c; //这里是this引用16 }17 public static void main(String[] args){18 SubClass bc = new SubClass(12,"哈喽",32.21);19 System.out.println(bc.a+" "+bc.b+" "+bc.c);20 }21 }
面向对象三大特征——继承