继承关系
两个类之间存在三种关系:
- 依赖,uses-a,如果一个类的方法操纵另一个对象,我们就说一个类依赖于另一个类。
- 聚合(关联),has-a,一个对象包含另外一个对象,聚合关系意味着类A的对象包含类B的对象。
- 继承,is-a,如果两个类之间存在明显的is-a(是)关系,例如每个经理都是雇员,那这两个类有继承关系。
例如:
1
2
3
4 1class Manager extends Employee{
2 ......
3}
4
Manager继承了Employee类,继承可以重写超类的方法,也可以添加方法,即子类比超类拥有的功能更加丰富。
方法重写
当子类重写超类的方法时,也可以调用超类的同名方法,只需要使用super.method()。要注意,
重写的方法不可低于超类方法的访问权限!
例如:
1
2
3
4
5
6 1//重写getSalary方法
2 public double getSalary(){
3 double baseSalary = super.getSalary();//调用了超类的getSalary方法
4 return baseSalary + bonus;
5 }
6
1
2 1子类重写了getSalary()方法,也调用了超类的同名方法。
2
另外,super()方法也可以在构造器中使用,以便调用超类的构造器方法。要注意的是super()方法必须是子类构造器的第一条语句。否则编译器会给出Constructor call must be the first statement in a constructor的错误提醒。例子见最后大例子。
多态和动态绑定
一个对象(例如下例中的e)能够引用多种实际类型的现象称为
多态,在运行时能够自动的选择调用那个方法的想象成为
动态绑定。Java不支持多重继承,仅支持单继承。
例如下面的大例子中,Emplyee类型的e可以引用Emplyee类型,Manager类型以及Boss类型的对象,当调用e.getSalary()的时候,编译器知道具体的e的实际类型,从而准确的调用该实际类型类的getSalary方法,如果不存在,那就调用其超类的该方法,这就是动态绑定。
final
阻止继承。
1
2
3
4
5
6
7
8
9
10
11
12 1class Employee{
2 ......
3 public final String getName(){
4 return name;
5 }
6 ......
7 }
8
9 final class Manager extends Employee{
10 ......
11 }
12
1
2 1如上例中,Manager类不可以再被继承了,而getName方法也不可被子类重写。
2
强制类型转换
进行强制类型转换的原因:在暂时忽视对象的实际类型之后,使用对象的全部功能。
仅可以在继承链上从上向下进行转换,如把实际类型是Manager的Employee类型的staff[1]转换成Manager类型。
1
2 1Manager man = (Manager)staff[1];
2
例子
总结性的大例子:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 1package com.xujin;
2
3public class Test {
4 public static void main(String[] args) {
5 Employee[] staff = new Employee[3];
6 staff[0] = new Employee("Bob", 1000);
7 staff[1] = new Manager("Jim", 5000, 1000);
8 staff[2] = new Boss("Alice", 7000, 1000, 10000);
9
10 for(Employee e : staff)
11 System.out.println("class name:" + e.getClass().getName() + "\tid:" + e.getId() +
12 "\tname:" + e.getName() + "\tsalary:" + e.getSalary());
13
14 Manager man = (Manager)staff[1];
15 Boss boss = (Boss)staff[2];
16 System.out.println(man.getBonus());//类型转换后就可以使用实际类型的全部功能
17 System.out.println(boss.getAward());
18
19 //ClassCastException异常,不允许进行继承链上的从上到下的转换
20 //Boss myBoss = (Boss)staff[0];
21
22 //把instaceof运算符和类型转换组合起来,避免异常
23 if(staff[0] instanceof Boss){
24 System.out.println("staff[0] is a instace of Boss");
25 Boss myBoss = (Boss) staff[0];
26 }
27 else System.out.println("staff[0] isn't a instace of Boss");
28
29 if(staff[2] instanceof Boss){
30 System.out.println("staff[2] is a instace of Boss");
31 }
32 else System.out.println("staff[2] isn't a instace of Boss");
33
34 }
35}
36
37class Employee{
38 public Employee(String name){
39 this.name = name;
40 id = nextId;
41 nextId++;
42 }
43
44 public Employee(String name, double salary){
45 this(name);//调用另一构造器
46 this.salary = salary;
47 }
48
49 //定义访问器方法
50 public final String getName(){
51 return name;
52 }
53
54 public double getSalary(){
55 return salary;
56 }
57
58 public final int getId(){
59 return id;
60 }
61
62
63 //定义更改器方法
64 public final void setName(String name){
65 this.name = name;
66 }
67
68 public final void setSalary(double salary){
69 this.salary = salary;
70 }
71
72 public final void raiseSalary(double percent){
73 this.salary *= (1 + percent);
74 }
75
76 //定义变量
77 private String name = "";//实例域初始化
78 private double salary;
79 private int id;
80 private static int nextId = 1;
81
82}
83
84class Manager extends Employee{
85 public Manager(String name, double salary, double bonus){
86 super(name, salary);//super在构造器中的使用,可以调用超类的构造器
87 setBonus(bonus);
88 }
89
90 public double getBonus(){
91 return bonus;
92 }
93
94 //重写getSalary方法
95 public double getSalary(){
96 double baseSalary = super.getSalary();//调用了超类的getSalary方法
97 return baseSalary + bonus;
98 }
99
100 public void setBonus(double bonus){
101 this.bonus = bonus;
102 }
103
104 private double bonus;
105}
106
107final class Boss extends Manager{
108 public Boss(String name, double salary, double bonus, double award){
109 super(name, salary, bonus);
110 this.award = award;
111 }
112
113 //重写getSalary方法
114 public double getSalary(){
115 double baseSalary = super.getSalary();//调用了超类的getSalary方法
116 return baseSalary + award;
117 }
118
119 public double getAward(){
120 return award;
121 }
122 private double award;
123}
124
抽象类
最后,阐述一下抽象类的概念。
抽象类就是一个专门用来扩展的祖先类,抽象类本身不能定义一个该类的对象,即抽象类不能被实例化。
1
2 1Person p = new Student("joun", 17, 6000);
2
1
2 1这里p是一个person类型的变量,但是它引用了Student类型的实例。
2
抽象类中的方法有两种,一种是普通的,和一般类中的方法一样,另一种是抽象方法,起一个占位的作用,将来子类继承会实现这种方法。
类即使不含抽象方法,也可以将类声明为抽象方法。
抽象类的抽象方法可以用来实现多态性,例如下例中在抽象类中定义了一个getFee()方法,两个子类Employee和Student分别实现了它,但是用了不同的实现方法,当通过Person类型的p调用getFee()方法时,就会根据p的实际类型来调用确定的方法。
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 1package com.xujin;
2
3public class Test {
4 public static void main(String[] args) {
5 Person[] people = new Person[2];
6 people[0] = new Employee("Bod", 34, 5000);
7 people[1] = new Student("Joun", 17, 6000);
8
9 for(Person p: people){
10 System.out.print(
11 "Name:" + p.getName() +
12 "\tAge:" + p.getAge() +
13 "\tDescription:" + p.getDescription() + "\t");
14 if(p instanceof Employee){
15 System.out.println(((Employee) p).getFee());
16 }
17 else if(p instanceof Student)
18 System.out.println(((Student) p).getFee());
19 }
20 }
21}
22
23abstract class Person{
24 public Person(String name, int age){
25 this.name = name;
26 this.age = age;
27 }
28
29 public abstract String getDescription();
30
31 public final String getName(){
32 return this.name;
33 }
34
35 public final void setName(String name){
36 this.name = name;
37 }
38
39 public final int getAge(){
40 return this.age;
41 }
42
43 public final void setAge(int age){
44 this.age = age;
45 }
46
47 private String name;
48 private int age;
49}
50
51class Employee extends Person{
52 public Employee(String name, int age, double fee){
53 super(name, age);
54 id = nextId;
55 nextId++;
56 this.fee = fee;
57 }
58
59 //定义Person抽象类的抽象方法
60 public String getDescription(){
61 return "This is an employee. class name:" + this.getClass().getName();
62 }
63
64 //定义访问器方法
65 public double getFee(){
66 return fee * 2;
67 }
68
69 public final int getId(){
70 return id;
71 }
72
73 //定义更改器方法
74 public final void setFee(double salary){
75 this.fee = fee;
76 }
77
78 //定义变量
79 private double fee;
80 private int id;
81 private static int nextId = 1;
82}
83
84class Student extends Person{
85 public Student(String name, int age, double fee){
86 super(name, age);
87 this.fee = fee;
88 }
89
90 public String getDescription(){
91 return "This is a student. class name:" + this.getClass().getName();
92 }
93
94 public double getFee(){
95 return this.fee;
96 }
97
98 public void setFee(double fee){
99 this.fee = fee;
100 }
101
102 private double fee;
103}
104
1
2 1 结果:
2