zoukankan      html  css  js  c++  java
  • 关于继承与多态

     关于继承与多态的几点总结

    1、父类的所有方法都能被继承吗?能被重写吗?能表现出多态性吗?

    1.1 非静态方法

      1.1.1 被public、default、protected修饰的非静态方法

      能被子类继承,如果没有被final修饰,则能被重写,当父类引用指向子类对象时,表现出多态性。

      1.1.2 被private修饰的非静态方法

      不能被子类继承,更不能被重写,没有多态性(有的人理解为父类的所有包括私有的成员都能被继承,只是在子类中不可见,我更倾向于前者)。当子类中出现与父类私有方法名和参数相同的时候会发生什么呢?

    class Parent{
        private void f() {
            System.out.println("parent");
        }
        public static void main(String[] args) {
            Parent p = new Child();   
            p.f();
        }
    }
    class Child extends Parent{
        public void f() {         //父类的私有方法在子类中不可见,子类的f()方法是一个全新的方法,编译器认为f()方法没有被重写
        System.out.println("child"); 
      }
    }

    打印结果:

    parent

    1.2 静态方法

      静态方法可以被继承,不能被重写,也就不能表现出多态性

    class Parent{
        public static void f() {
            System.out.println("parent");
        }
    }
    class Child extends Parent{
        public static void f() {
            System.out.println("child");
        }
        public static void main(String[] args) {
            Parent p = new Child();   //静态方法能被继承,但不能被重写
            p.f();
            Child c = new Child();
            c.f();
        }
    }

    打印结果:

    parent
    child

     1.3 构造方法

      构造方法不能被继承,不能被重写,没有多态性。

      构造方法既不是静态方法也不是非静态方法,构造方法中会有一个this对象作为参数传进去,所以我们可以在构造方法内部对对象属性进行初始化,也可以在构造方法内调用非静态方法。

      如果该非静态方法被重写过,那么构造器内部会不会存在多态行为呢?参考Java编程思想中的一个例子:

    class Glyph {
        void draw() {
            System.out.println("Glyph.draw()");
        }
    
        Glyph() {
            System.out.println("Glyph() before draw()");
            draw();
            System.out.println("Glyph() after draw()");
        }
    }
    
    class RoundGlyph extends Glyph {
        private int radius = 1;
        RoundGlyph(int r) {
            radius = r;
            System.out.println("RoundGlyph.RoundGLyph(), radius = " + radius);
        }
        void draw() {
            System.out.println("RoundGlyph.draw(), radius = " + radius);
        }
    }
    
    class RolyConstructors {
        public static void main(String[] args) {
            new RoundGlyph(5);
        }
    }

      在父类构造器中调用被子类重写的非静态方法,会发生多态行为,但这并不是我们想要的结果,原因如下:

    1. 在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的零;
    2. 如前所述那样调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0;
    3. 按照声明的顺序调用成员的初始化方法;
    4. 调用导出类的构造器主体。

      因此,在编写构造器中有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。在构造器中,唯一能够安全调用的是基类中的final方法(包括private方法),因为这些方法不能被子类覆盖,也就不会出现上述的问题。

    2、父类的所有属性都能被继承吗?能被重写吗?能表现出多态性吗?

    2.1 被public,default,protected修饰的属性

      都能被继承(与是否是静态的无关),不能被重写,没有多态性。当子类中定义了与父类相同的属性时,子类会在不同的存储空间同时保留自己的和父类的属性

    class Child extends Parent {
        public static int a = 2;
        public void getA() {
            System.out.println("a = "+a);
        }
        public void ParentA() {
            System.out.println("super.a = " + super.a);
        }
        public static void main(String[] args) {
            Parent p = new Child();
            System.out.println(p.a);  //任何域访问操作都由编译器解析
            Child c = new Child();
            c.getA();     //直接访问field默认会获取自己的域
            c.ParentA();  //通过super.field能获取父类的域
        }
    }

    2.1 被private修饰的属性

      个人理解为可以被继承,但是不能直接访问,能通过父类public、default、或protected方法间接访问(也有人理解为不能为继承)

    class Parent {
        private int a;
        public Parent(int a) {
            this.a = a;
        }
        public int getA() {
            return a;
        }
    }
    
    class Child extends Parent {
        public Child(int a) {
            super(a);
        }
        public static void main(String[] args) {
            Child c = new Child(1);    
            System.out.println(c.getA());  //结果为1
        }
    }

       当父类和子类存在相同私有属性时:

    class Parent {
        private int a;
        public Parent(int a) {
            this.a = a;
        }
        public int getA() {
            return a;
        }
    }
    
    class Child extends Parent {
        private int a = 2;
        public Child(int a) {
            super(a);
        }
        public static void main(String[] args) {
            Child c = new Child(1);    
            System.out.println(c.getA());  //1
            System.out.println(c.a);       //2
        }
    }

       关于继承与多态以及对象初始化过程还有很多不是很理解的地方,先记录下来,等日后有时间研究一下java虚拟机的原理再来完善!

  • 相关阅读:
    HDU 5744
    HDU 5815
    POJ 1269
    HDU 5742
    HDU 4609
    fzu 1150 Farmer Bill's Problem
    fzu 1002 HangOver
    fzu 1001 Duplicate Pair
    fzu 1150 Farmer Bill's Problem
    fzu 1182 Argus 优先队列
  • 原文地址:https://www.cnblogs.com/xiaohang123/p/12070385.html
Copyright © 2011-2022 走看看