4.1 继承
实际场景:
如我们有一个Person的类,该类中有姓名、性别、年龄三个属性以及打印信息的方法。
我们还有一个学生类,该类中也是姓名、性别、年龄是三个属性及打印信息的方法
此外,我们还有工人类、教师类等,也是上述属性和方法(或者在上述属性基础上还有别的属性,在上述方法基础上还有别的方法)。
如果Person类、学生类、工人类,教师类等一个个去写,关于姓名、性别、年龄、打印属性的方法这些代码就会重复好几遍,此时可以使用继承(和python)一致。可以先写一个Person类,让学生类、工人类、教师类都继承Person类。Person类称为父类,学生类、供人类、教师类等都称为子类
如下图,写好一个Person的类
然后让Student类去继承Person
4.2 单继承和多层继承
java只允许单继承和多层继承。单继承指一个子类只能有一个父类,但是一个父类可以有很多子类。多层继承即子类继承父类,该父类还可以有一个父类,如下图:
举例如下:
4.3 方法的重写
方法重写就是子类的方法覆盖父类的方法
方法重写时,上方用@override修饰,可以使用alt+/快捷键快速进行方法重写。如图,先alt+/,然后选择红框
结果如下图所示:
super为调用父类,这里用不到,可以删除。最终可以写成上图中注释处的内容。
在这里注意和方法的重载相区分。
4.4 关键词super
4.4.1 super简介
java中的super和python的super一样,都是调用父类。
4.4.2 调用父类的构造器
- 当父类有无参的构造器或者没有写任何构造器时,子类的所有构造器都会默认调用父类的无参构造器(包括父类没写任何构造器时的默认无参构造器)。注意这里句有个默认调用,也就是不写任何东西时,调用父类无参的构造器,当写了某些代码后,就不是调用父类无参构造器了。具体这个代码是什么,下述会讲。
前提知识回顾:无论是python还是java,对于一个类,初始化时,就相当于执行了构造器函数,python就相当于执行了def __init__()
这个函数,假如def __init__()
下面写了print(123),那么一旦实例化,就会立刻打印123。java也是一样的,一旦实例化,就会执行构造器下的代码。所以子类的构造器,一方面是创建自身的构造器,另一方面是调用父类的构造器。
回归正题,假如ManKind是一个父类,并且有一个无参的构造器,下面打印ManKind这个字符串
现有一个子类Kids,继承自ManKind,当实例化后,下方打印出了mankind这个字符串
其效果相当于显性调用了父类的无参构造器,如下所示
回顾一下python
上图中子类fireMan的构造器中有一个参数name,其实就是子类的构造器调用了父类的构造器。故def __init__(self, name)
有两重含义,第一是子类本身的构造器;第二,name参数表明调用了父类的构造器。 - 当父类没有空参数的构造器时,子类构造器必须通过this(参数列表)或者super(参数列表)指定调用本类或父类中相应的构造器。
还是以父类ManKind为例,其只有一个有参的构造器。
子类的构造器必须显示地指定调用父类的有参构造器,写法如下:
怎样理解调用本类或父类中相应的构造器中的调用本类呢?难道可以不调用父类?其实不是的。想一想,假如本类中有一个构造器,暂时称为a,又有一个构造器b。那么b调用a会不会报错呢?答案不会。因为b调用了a,而a肯定调用了父类的构造器(无论是不是有参的),所以b调用a,相当于借助a调用了父类的构造器,故子类的构造器无论如何都会调用父类构造器的。有的是直接调用,有的是间接调用(通过本类的其他构造器调用父类的构造器) - 当父类既有无参构造器,又有有参构造器时,子类想要调用有参构造器(不是默认调用无参构造器),可以用2中的this(参数列表)或者super(参数列表)指定调用本类或父类中相应的构造器。
总结:子类的构造器一定会调用父类构造器的
4.4.3 java中构造器及子类调用情况总结
4.4.4 super和this的区别
4.5 实例化过程
4.6 多态性