zoukankan      html  css  js  c++  java
  • 面向对象三大特征——继承

    继承 :子类继承父类,子类将得到父类的全部方法和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 BaseClass
    14 {
    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 BaseClass
    11 {
    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?这也得分三种情况讨论:

      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 BaseClass
    11 {
    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 }

     4、继承的硬伤,破坏封装

      1、继承是实现类复用的重要手段,但破坏了封装,而采用组合方式实现类复用则提供更好的封装性。
      2、子类如果继承及父类的全部方法和Field,那么父类将完全暴露在子类下,如何不让子类随意修改父类:
          1、尽量隐藏父类的内部数据,将成员变量设置成private访问类型。
          2、不要让子类随意访问、修改父类方法,用private修饰父类方法限制子类访问,用final修饰父类方法防止子类重写,用protected父类方法限制只能被子类重写。
          3、尽量不要在父类构造器中调用将要被子类重写的方法。

  • 相关阅读:
    Vue2.1.7源码学习
    JavaScript 复制对象【Object.assign方法无法实现深复制】
    数组去重你知道几种?
    基于webpack2.x的vue2.x的多页面站点
    欲练JS,必先攻CSS——前端修行之路
    闭包的7种形式
    遇见未知的CSS
    redux 个人整理
    log4j.properties打印日志信息(1)
    Java Web开发之Servlet、JSP基础
  • 原文地址:https://www.cnblogs.com/manliu/p/3985263.html
Copyright © 2011-2022 走看看