ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

继承和多态

2022-08-08 19:04:36  阅读:212  来源: 互联网

标签:setValue 继承 子类 多态 value getValue 构造 父类


0 概念

.1 继承 关键字:extends 关系:is-a

  • 概念:手机和iPhone就像是继承关系,iPhone is a mobile phone。
  • 格式:public class Iphone extends Phone{}
  • 子类的特点:可以有父类的内容,还可以有自己特有的内容。Iphone可以有电话都有的打电话发信息的功能,还有面部解锁、全景拍照等自己的功能。
  • Java中只支持单继承

.2 super关键字和this关键字

  • this:代表对本类对象的引用
  • super:代表对父类对象的引用

.3 继承中的构造方法-ref:为何需要无参构造?

  1. 子类中所有构造方法默认都会访问父类中 无参的构造方法

因为子类会继承父类中的数据,还可能使用父类中的数据。 因此子类初始化之前,一定要先完成父类数据的初始化。所以每一个子类构造方法的第一句都是super()。根据关键词的意思,该语句的意思就是引用父类的无参构造。若父类没有无参构造,则编译时会发生错误。
如图所示,A类的有参构造override默认的无参构造,则不具备无参构造。而B想要调用super()是会编译报错的,这也是一个类需要无参构造的原因。(虽然也可以通过super父类有参构造,但是不推荐)

.3 多态

  1. 什么叫多态?
    有继承或实现关系+此方法重写+有父类引用指向子类对象这三个条件是多态的前提。BTW,父类引用指向子类对象的行为又叫做向上转型
  2. 多态中成员访问的特点
  • 成员变量,编译看左边,执行看左边
  • 成员方法,编译看左边,执行看右边
    成员方法有重写,成员变量没有,所以不一样。
    例子:
    父类A:成员变量a,一个无参构造,一个有参构造,一个get方法。

    子类B:成员变量a,一个重写了父类的无参构造,一个自己仅有的方法onlyB。

    测试一下多态的结果:

子类构造执行肯定先执行父类的构造。若没有写super,则默认使用父类的无参构造。

1 例子

通过一个例子加深对继承和多态的理解。

class Test {
    public static void main(String[] args) {
        System.out.println(new B().getValue());
    }
    static class A {
        protected int value;
        public A (int v) {
            setValue(v);
        }
        public void setValue(int value) {
            this.value= value;
        }
        public int getValue() {
            try {
                value ++;
                return value;
            } finally {
                this.setValue(value);
                System.out.println(value);
            }
        }
    }
    static class B extends A {
        public B () {
            super(5);
            setValue(getValue()- 3);
        }
        public void setValue(int value) {
            super.setValue(2 * value);
        }
    }
}

输出的结果应该是什么?

2 分析

我把两个类并排放在一起,这样看起来方便一点。

  1. 进入主函数,分析程序执行的顺序。 第一模块,执行new B(),创建对象。 第二模块,执行B.getValue(),调用对象的方法。第三模块,sout输出语句,输出函数的返回值。按照顺序进行分析。
  2. 第一模块:new B(),创建类B的对象。
    2.1 进入B的构造。先执行super(5).已知B类继承A类,所以要先完成父类A的构造。B类继承了A类的有参构造super(A),传递了参数v=5.
    2.2 进入A的构造,A的构造调用了方法setValue(5)。而子类B重写了父类A的该方法,调用B的setValue。
    2.3 进入B的setValue(5),方法体内指向父类的setValue方法,参数v = 2 * value = 10
    2.4 进入A的setValue(10),this.value = value = 10。B实例的value=10.
    2.5 A的构造执行完毕。
    2.6 再执行setValue(getValue()- 3); 先执行getValue()。B没有重写该方法,调用父类的getValue()
    2.7 进入B的getValue()。执行try内语句。B.value++,B.value=11,return 11.getValue()返回11.
    2.8 就算return,finally还是会执行。执行finally内语句。调用setValue(11),同理,进入子类重写的setValue(11).进入B的setValue(11),引用父类的setValue(11*2),进入A的setValue(22),此时B.value=22.输出22,而前面11已经作为函数的返回值返回了。
    2.9 再执行setValue(getValue()-3)即setValue(11-3)=setValue(8)。
    2.10 进入B的setValue(8),super.setValue(16),进入A的setValue(16),B.value=16。
    2.11 B的构造执行完毕。
  3. 第二模块,实例B.getValue(),继承A的getValue()
    3.1 进入try内。value++,B.value=17。return value。返回值17.
    3.2 进入finally内。this.setValue(17),调用B的setValue(17),进入A的setValue(17 * 2),B.value=34。输出34.
  4. 第三模块,输出返回值。之前已经返回了17,所以输出17.

所以输出的结果应该是22 34 17。

标签:setValue,继承,子类,多态,value,getValue,构造,父类
来源: https://www.cnblogs.com/80sVolxxxx/p/16562915.html

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有