Java面向对象编程之 继承性 | Java OOP Inheritance
Made by Mike_Zhang
(二次更新:2021-09-18)
Java主题:
OOP Introduction
请阅读本博客的Java面向对象编程详细介绍 - Java OOP Detailed Introduction
继承性(Inheritance)
类的继承是OOP中非常重要的概念, 它的核心思想是扩展某一个父类, 得到一个子类. 子类继承类它的父类的属性和方法, 子类也可以有新的不同于父类的属性和方法, 也可以重写父类中的一些方法. 举例来说, 定义一个父类为三角形类, 而直角三角形类就是三角形类的子类, 子类拥有父类具有的属性和方法, 直角三角形类也拥有其父类不具有的属性和方法, 比如说直角三角形类的一个角为90度 这一属性就是直角三角形类特有的属性,同样也可以重写父类具有的属性和方法。
extends
是Java中用来表明继承关系的关键字
以下为例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56public class Triangle { // 三角形类
public Triangle(){ //父类构造方法
System.out.println("This is Triangle");
}
public Triangle(int i){ //父类有参构造方法
System.out.println("A angle of the Triangle is " + i);
}
private float triangleAngleA, triangleAngleB, triangleAngleC;
public void setAngle(){
System.out.println("Please set triangleAngleA, B and C");
}
protected void getTriangleAngle(){ //成员方法
System.out.println("triangleAngleA + triangleAngleB + triangleAngleC = 180");
}
}
class RightTriangle extends Triangle{ //定义直角三角形子类继承三角形父类
public RightTriangle(){ //子类构造方法
System.out.println("This is Right Triangle");
}
public RightTriangle(int i){ //子类有参构造方法
super(i);
System.out.println("A angle of the Right Triangle is " + i);
}
public void setRightAngle(){ //在子类中添加新的成员方法
System.out.println("triangleAngleC is 90");
}
public void getTriangleAngle(){ //重写父类中的成员方法
System.out.println("triangleAngleC = 90, and ");
super.getTriangleAngle(); //调用父类方法
}
}
class IsoscelesRightTriangle extends RightTriangle{ //定义等腰直角三角形子类继承直角三角形父类
public IsoscelesRightTriangle(){ //子类构造方法
System.out.println("This is Isosceles Right Triangle");
}
public IsoscelesRightTriangle(int i){ //子类有参构造方法
super(i);
System.out.println("A angle of the Isosceles Right Triangle is " + i);
}
public void setIsoscelesRightAngle(){ //在子类中添加新的成员方法
System.out.println("triangleAngleA and B are 45, triangleAngleC is 90");
}
public void getTriangleAngle(){ //重写父类中的成员方法
System.out.println("triangleAngleA & B = 45, and ");
super.getTriangleAngle(); //调用父类方法
}
public static void main(String[] args){ // 主函数 main()
IsoscelesRightTriangle x = new IsoscelesRightTriangle(); // 创建一个等腰直角三角形类的方法
x.setAngle(); // 调用三角形类的方法
x.setRightAngle(); // 调用直角三角形类的方法
x.setIsoscelesRightAngle(); // 调用本类的方法
}
}
运行结果:
1 |
|
1. 被继承的成员
当一子类继承父类后,父类的实例变量将成为子类的一部分,父类的属性和方法可以被继承到子类,但是构造方法、static initializer、instance initializer并不是实例变量,所以不可以被继承。
判断实例变量是否可以继承到子类中,需要根据子类对父类实例变量的可访问性(accessibility)。子类继承了父类的某一成员,说明子类是可以访问到这一成员的。
2. 重写方法
子类只能重写能够从父类中继承的方法,否则,如private
修饰的方法不能被重写。
重写的方法必须有相同的Signature (i.e. method name, method argument type list),如:
1 |
|
3. 权限修饰符
一般来说,为了保护继承性,成员属性修饰为private
,成员方法修饰为public
。尽管protected
修饰的属性和方法可以在继承类间访问,但是最好还是让成员属性被private
修饰。
子类在重写父类中的方法时, 权限的修改范围只能从小到大, protected修饰的方法只能重写成public, 而不能重写成private;
4. super
关键字
super
关键字与this
关键字的作用十分类似。
注意到例子三个类中都有getTriangleAngle()
方法,因为子类可以使用或者修改父类中的方法。但是不能直接使用getTriangleAngle()
语句调用父类方法,这样会造成自我循环调用的错误。需要使用super
关键字来引用到目前子类的父类,如super.getTriangleAngle()
,意思为调用目前子类的父类的getTriangleAngle()
方法。但是只能调用public和protected修饰的方法。
5. 构造方法
在Java中构造方法不会被继承,构造方法分为无参构造方法和有参构造方法。
5.1 无参构造方法
当子类创建对象时,会先调用其父类的无参构造方法。而父亲必须包含一个无参构造方法,否则子类无法隐形调用其父类的无参构造方法。
例子中,
mian()
中创建了IsoscelesRightTriangle
类的x
对象,它会调用其父类RightTriangle
的构造方法,而在RightTriangle
被调用时,需要先调用其父类Triangle
的构造方法,一层层向上。
因此最先完成调用的是最大的父类Triangle
的构造方法,因此先输出This is Triangle
,再完成调用子类RightTriangle
的构造方法,输出This is Right Triangle
,最后完成调用子类IsoscelesRightTriangle
的构造方法,输出This is Isosceles Right Triangle
,一层层向下。
因此,运行后输出为:
1 |
|
注意:
子类构造方法的第一句语句一直都是调用某一构造方法,可以是:
- 对子类构造方法的显性重载,使用
this
关键字; - 对其父类构造方法的显性调用,使用
super
关键字; - 隐性调用其父类的无参构造方法,当没有显性调用构造方法时,编译器会自动调用,使用
super
关键字,如:就算子类
IsoscelesRightTriangle
没有构造方法,Java编译器也会自动调用其父类的构造方法。
举例:
1 |
|
C cObj = new C();
的输出为1435
5.2 有参构造方法
父类无参构造方法能够被自动调用,但是调用父类有参构造方法需要在子类构造方法中用super
关键字表明,若无,则不会调用。如下:
修改例子中的main()方法,其余不变,以测试有参构造方法:
1 |
|
输出结果:
1 |
|
注意:
在子类中,调用其父类构造方法的语句 必须是 此子类构造方法体中的 第一行被执行的语句 ,否则会报错,例子:
1 |
|
报错:Call to 'super()' must be first statement in constructor body
6. Object
类
就算某一个类没有确切表明继承了父类,此类也已经自动的继承了java.lang.Object
类,此为Java中的统一父类(Universal Superclass)。
参考
B. Eckel, Thinking in java. Upper Saddle River, N.Y. Prentice Hall, 2014.
M. Goodrich, R. Tamassia, and A. O’reilly, Data Structures and Algorithms in Java, 6th Edition. John Wiley & Sons, 2014.
写在最后
Java中OOP相关的知识是十分重要的, 会继续更新.
最后,希望大家一起交流,分享,指出问题,谢谢!
原创文章,转载请标明出处
Made by Mike_Zhang