面向对象的第二大特征:继承性
一、什么是继承?
定义
子类继承了父类,就拥有了父类的方法和属性(私有的除外);
在子类中,可以使用父类中定义的方法和属性,也可以创建新的属性和方法,同时可以重写父类的方法;
一个子类还可以派生其他的子类,这些派生子类也可以继承其父类的父类。
因而,子类通常比父类的功能更多。
在Java 中,继承的关键字用的是“extends”,即子类是对父类的“扩展”。
比如:
现有学生类和工人类,两个类都有定义name和age属性,和吃饭的方法,此外学生类中还定义了学号属性,工人类定义了工号属性。我们可以把学生类和工人类中相同的属性和方法提取出来写进一个类,再让学生类和工人类分别继承这个类,这样就方便多了。
其中Person类是父类,Student类是子类。
可以看出,子类是可以调用父类的属性和方法的。
优缺点
- 优点:提高了代码复用性。
- 缺点:由于继承会有多层的继承关系,会提高他们之间的依赖关系,耦合度会变高。
语法
class 子类 extends 父类{
}
生成setter and getter方法、构造方法
- setter and getter
右击 - source - Generate Getters and Setters - Select All - 构造方法
右击 - source - Generate Constructor using Fields - (勾选形参列表)
注意
-
所有类的父类都是Object
如果一个类没有显式地定义其父类,那么它的父类就是Object类。 -
Java只支持单继承,不允许多重继承
一个子类只能有一个父类;
一个父类可以派生出多个子类。
练习
1.(1)定义一个ManKind类,包括
成员变量 int sex 和 int salary;
方法 void manOrWorman():根据sex的值显示“man”(sex1)或者“women”(sex0);
方法 void employeed():根据salary的值显示“no job”(salary ==0)或者“ job”(salary!=0)。
(2)定义类Kid继承ManKind,包括
成员变量 int yearsOld;
方法 printAge() 打印 yearsOld 的值。
(3)在测试类TestKid的main方法中实例化Kid的对象 someKid,用该对象访问其父类的成员变量及方法。
//ManKind类(父类)
//Kid类(子类)
//测试类TestKid
2.根据下图实现类。在TestCylinder类中创建Cylinder类的对象,设置圆柱的底面半径和高,并输出圆柱的体积。
圆柱对象调用findArea()
//圆类(父类)
//圆柱类(子类)
//测试类TestCylinder
二、 方法重写(Override)
为什么要使用方法重写?
如果父类的方法满足不了子类需求时,子类可以对父类的方法进行重写。
比如,在上述的圆与圆柱的例题中,如果我想要通过圆柱对象cy调用面积计算方法findArea()来计算cy的表面积,即cy.findArea(),这样实际上是行不通的。因为findArea()里写的是计算圆面积的方法,即使通过cy调用算出来的也是圆的面积。怎么解决该问题呢?
答:用方法重写(Override)
重写规则
(1)要求子类重写的方法名、参数列表、返回值类型必须和父类完全一致;
(2)子类重写方法的访问修饰符权限不能低于父类方法修饰符权限;
(3)子类方法和父类方法必须同为static或非static。
方法重载(Overlord)与方法重写(Override)的区别
- 方法重载必须在同一个类中,方法重写必须存在继承关系;
- 方法重载要求方法名相同,参数列表必须不同,与返回值无关;
- 方法重写要求子类重写的方法名、参数列表、返回值类型必须和父类完全一致。
·例题
以上面的Person和Student为例,重写Student类中吃饭的方法:
四种访问权限修饰符
权限:
public>protected>default>private
- protected:在同一个包下或其他包中的子类中使用
- default:只能在同一个包下使用
三、super关键字
为什么使用super?
我们在子类中定义的属性、方法、构造方法可能会和调用的父类重名,用super加以区分父类和子类(super用于修饰父类);同时也可以避免系统根据就近原则调用子类的情况。
定义
super关键字用以修饰父类的属性、方法、构造方法:
1.当前子类和父类的属性出现重名时,默认会调用子类的属性(就近原则),可以通过“super.属性名”的方式显式的调用父类声明的同名属性。
2.子类重写父类方法后,如果子类想再次调用父类被重写的方法,可以通过“super.方法名()”的方法调用父类方法。
3.super可以修饰 构造方法,通过子类构造方法中使用“super(形参)”来显式的调用父类对应的构造方法。
- super修饰属性
- 通过“super.属性名”的方式显式的调用父类声明的同名属性
例:父类和子类中同有Id属性,父类中的Id为身份证号,子类中的Id为学号:
- super修饰构造方法
- 通过“super(形参)”来显式的调用父类对应的构造方法
例:在父类中定义一个无参构造方法,在子类中显式的调用该构造方法,结果输出为:
可以看出,在执行student()构造方法时调用了父类的Person()构造方法。
如果不在子类构造方法中显式的声明调用父类构造方法,在子类构造方法执行时还会调用父类构造方法吗?
答:会,系统默认调用父类无参构造方法。
注意:
- super(形参)必须声明在首行。
- this(形参)也必须声明在首行,这说明this(形参)和super(形参)只能选择一个使用。
- 在构造方法中,不显式地通过super(形参)的方式调用父类对应的构造方法,默认会调用父类的无参构造方法。
- super修饰方法
- 通过“super.方法名()”的方法调用父类方法
例:通过调用findArea()方法计算圆柱体表面积
可以看到,在上面子类的findArea()方法中,也调用了父类的findArea()方法,如果不在父类的findArea()前加super的话,系统会跟据就近原则,调用子类findArea()。也就是说,在子类findArea()方法里调用了子类findArea()方法,这显然是错误的。