初探Java继承

萌新刚学Java,对其继承机制有些疑问,在此小小总结一下,当然不会很全面,到寒假里再详细介绍。

概述

继承是Java复用代码的有效手段之一,它通过已定义的类来产生一个新类。
在Java中,继承用extends关键字声明,其中被继承的被称为父类基类,通过继承基类而产生的新类被称为子类派生类

继承的规则

当子类和父类在同一个包内时,子类可以获得父类的所有非private域和方法,否则子类将获得父类的所有publicprotected域和方法。但子类不能继承父类的任何构造方法。
如果子类和父类的某个可继承方法名相同,则子类的这个方法会覆盖父类的同名方法,但在这之后我们要访问父类的这个方法也是可以的,使用super关键字。域也是同理,下面放个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Person {
public void talk() {
System.out.printf("I am a Person.\n");
}
public static void main(String[] args) {
Student s = new Student();
s.talk();
s.talk2();
}
}

class Student extends Person {
public void talk() {
System.out.printf("I am a Student.\n");
}
public void talk2() {
super.talk(); //调用父类中已被覆盖的方法
}
}
/**输出:
* I am a Student.
* I am a Person.
*/

父类被隐藏的域也是类似的。

注意

在一个子类继承自父类时,必须调用父类的一个构造方法。通常情况下如果父类有一个无参构造方法,则我们可以不在代码中显式调用它;但如果父类没有无参构造方法,则我们必须在子类的构造方法中显式调用父类的构造方法,否则程序将不会通过编译。下面是一个例子:

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 Person {
protected String name;
//该类没有无参构造方法,只有一个参数列表Person(String)的构造方法
public Person(String name) {
this.name = name;
}
public void talk() {
System.out.printf("I am a Person.\n");
}
public static void main(String[] args) {
Student s = new Student("LiuYuang");
s.talk();
s.talk2();
}
}

class Student extends Person {
public void talk() {
System.out.printf("I am a Student.\n");
}
public void talk2() {
super.talk();
}
public Student(String name) {
super(name); //必须显式调用父类构造方法
}
}
/**输出:
* I am a Student.
* I am a Person.
*/

向上转型

子类的对象可以看作是父类的对象。比如,有一个类Shape,还有一个类Circle,它继承自Shape。则我们可以这样写:

1
2
3
4
5
6
7
void draw(Shape shape) {
//do something
}
...
Circle circle;
draw(circle);
...

这时draw方法也是可以正常运行的。这就是Java的多态。

总结

在子类被初始化时,编译器会保证其父类已经被初始化(即调用父类的构造方法)。从而保障子类的正常运行。
Java不支持多重继承,但类可以实现多个接口,从而实现多重继承的效果。关于这一点soon后再写。