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虚拟机的原理再来完善!

  • 相关阅读:
    生活娱乐 工业机器人代替工人装配鼠标键盘
    生活娱乐 工商银行如何查询开户行
    生活娱乐 格力空气能热水器怎么样
    生活娱乐 岛城将开首家机器人餐厅
    生活娱乐 毕业生论文查重技巧
    Windows 老是弹出要自动拨号连接怎么办
    Office 针式打印机如何调节边距
    Office 如何打印彩色照片能取得较好的效果
    西游释厄传如何设置简化出招表
    [ES2019] Use JavaScript ES2019 flatMap to Map and Filter an Array
  • 原文地址:https://www.cnblogs.com/xiaohang123/p/12070385.html
Copyright © 2011-2022 走看看