java 三大特性之继承

前两天我们说了 Java 三大特性之封装,今天主要说说三大特性之继承

下面我们会通过继承的特点和对应的例子来分别进行说明。

子类拥有父类非 private 的属性,方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。

例子:

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
public class {
public static void main(String[] str) {
Son simple = new Son();
simple.method();
simple.printStr();
simple.method("simple");
}
}
class Father {
public String str = "Simple";
Father() {
System.out.println("This is the Father's " + str);
}
//父类的非private方法,子类可以调用
public void method() {
System.out.println("This is the Father's method");
}
public void method(String strs) {
System.out.println("This is the Father's method with param");
}
}
class Son extends Father {
//子类可以拥有自己的属性
private String ownStr = "ownStr";
Son() {
super();
System.out.println("This is the Son's " +
super.str);
}
//子类可以拥有自己的方法
public void printStr() {
System.out.println("This is the " +
"Son's method");
}
//子类可以重写父类的方法
public void method(String strs) {
System.out.println("This is the Son's method, " +
"which is overriding from Father");
}
}

​输出结果:

This is the Father’s Simple
This is the Son’s Simple
This is the Father’s method
This is the Son’s method
This is the Son’s method, which is overriding from Father

Java 的类继承是单继承,但是接口可以使用关键字 implements 实现多重继承(例子会在后面讲接口的时候详细说明)。
子类会默认调用父类的无参数构造器,但是如果父类没有无参构造器,子类必须要显式的指定父类的构造器(有参数),而且必须是在子类构造器第一行进行调用。

例子:

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
public class {
public static void main(String[] str) {
new GouZaoQiTwo();
new GouZaoQiFour("simple");
}
}
class GouZaoQiOne {
GouZaoQiOne() {
System.out.println("This is GouZaoQiOne");
}
}
class GouZaoQiTwo extends GouZaoQiOne{
//子类会默认调用父类的无参数构造器
}
class GouZaoQiThree {
GouZaoQiThree(String str) {
System.out.println("This is the gouzaoqi with param.");
}
}
class GouZaoQiFour extends GouZaoQiThree{
GouZaoQiFour(String str){
//如果父类没有无参构造器,子类必须要显式的指定父类的构造器(有参数),
//而且必须是在子类构造器第一行进行调用
super(str);
System.out.println("This is GouZaoQiFour");
}
}

输出结果:

This is GouZaoQiOne
This is the gouzaoqi with param.
This is GouZaoQiFour

继承后类型支持向上转型,比如 B 继承 A,那么B的实例也属于 A 类型。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class {
public static void main(String[] str) {
GouZaoQiTwo gouZaoQiTwo = new GouZaoQiTwo();
//method方法的参数实际要求的类型是GouZaoQiOne,
//但是因为GouZaoQiTwo是GouZaoQiOne的子类,
//所以可以通过向上转型来满足参数类型的需要
gouZaoQiTwo.method(gouZaoQiTwo);
}
}
class GouZaoQiOne {
public void method(GouZaoQiOne gouZaoQiOne) {
System.out.println("This is GouZaoQiOne");
}
}
class GouZaoQiTwo extends GouZaoQiOne{
}

继承提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系),慎用继承。

例子:

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
public class {
public static void main(String[] str) {
ZiXingChe ziXingChe = new ZiXingChe("sylan215");
DianDongChe dianDongChe = new DianDongChe("sylan215-1");
ziXingChe.run();
ziXingChe.sleep();
ziXingChe.reboot();
dianDongChe.run();
dianDongChe.sleep();
dianDongChe.power();
}
}
class ZiXingChe {
private String name;
ZiXingChe(String name) {
this.name = name;
System.out.println("This is a " + name);
}
public void run() {
System.out.println("I am a " + this.name + ", I can run");
}
public void sleep() {
System.out.println("I am a " + this.name + ", I need sleep");
}
public void reboot() {
System.out.println("I am a " + this.name + ", I need reboot");
}
}
class DianDongChe {
private String name;
DianDongChe(String name) {
this.name = name;
System.out.println("This is a " + name);
}
public void run() {
System.out.println("I am a " + this.name + ", I can run");
}
public void sleep() {
System.out.println("I am a " + this.name + ", I need sleep");
}
public void power() {
System.out.println("I am a " + this.name + ", I need power");
}
}

输出结果为:

This is a sylan215
This is a sylan215-1
I am a sylan215, I can run
I am a sylan215, I need sleep
I am a sylan215, I need reboot
I am a sylan215-1, I can run
I am a sylan215-1, I need sleep
I am a sylan215-1, I need power

看看合并后的代码:

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
public class {
public static void main(String[] str) {
ZiXingChe ziXingChe = new ZiXingChe("sylan215");
DianDongChe dianDongChe = new DianDongChe("sylan215-1");
ziXingChe.run();
ziXingChe.sleep();
ziXingChe.reboot();
dianDongChe.run();
dianDongChe.sleep();
dianDongChe.power();
}
}
class CheZi {
private String name;
CheZi(String name) {
this.name = name;
System.out.println("This is a " + name);
}
public void run() {
System.out.println("I am a " + this.name + ", I can run");
}
public void sleep() {
System.out.println("I am a " + this.name + ", I need sleep");
}
}
class ZiXingChe extends CheZi {
private String name;
ZiXingChe(String name) {
super(name);
this.name = name;
}
public void reboot() {
System.out.println("I am a " + this.name + ", I need reboot");
}
}
class DianDongChe extends CheZi {
private String name;
DianDongChe(String name) {
super(name);
this.name = name;
}
public void power() {
System.out.println("I am a " + this.name + ", I need power");
}
}

输出结果为:

This is a sylan215
This is a sylan215-1
I am a sylan215, I can run
I am a sylan215, I need sleep
I am a sylan215, I need reboot
I am a sylan215-1, I can run
I am a sylan215-1, I need sleep
I am a sylan215-1, I need power

总结下继承的特点:

  1. 子类拥有父类非 private 的属性、方法;
  2. 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展;
  3. 子类可以用自己的方式实现父类的方法;
  4. Java 的类继承是单继承,但是接口可以使用关键字 implements 实现多重继承;
  5. 子类会默认调用父类的无参数构造器,但是如果没有默认(无参数)的父类构造器,子类必须要显式的指定父类的构造器(有参数),而且必须是在子类构造器中做的第一件事;
  6. ​继承后类型支持向上转型,比如 B 继承 A,那么B的实例也属于 A 类型;
  7. 继承提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系),慎用继承;