Plain's Blog

休想打败我的生活🔥

  1. 1. 继承
  2. 2. 继承的基本实现
  3. 3. 继承的限制
  4. 4. 参考资料

继承

  • 父类也称作超类、基类等
  • Java只有单继承,没有像C++那样的多继承。多继承会引起混乱,不利于后期维护
  • Java中接口有多继承
  • 子类继承父类,可以得到分类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)
  • 一个类有默认的父类:java.lang.Object

下面编写两个类:Persion类和Student类

  • Persion类
1
2
3
4
5
6
7
8
9
10
11
class Persion{
private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}
}
  • Student类
1
2
3
4
5
6
7
8
9
10
11
class Student{
private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}
}

对比两段代码,可以发现代码有重复。在所有的代码之中,最具有重复意义的就是链表类,针对于每一个简单Java类或者是说其他的任何类,都编写一个链表程序,代码量庞大,而且不方便维护。

继承的基本实现

语法

1
class 子类 extends 父类{}

直接继承不扩充内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Persion{
private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}
}

class Student extends Persion{

}

public class ExtendsTest{
public static void main(Strin args []){
Student stu = new Student();
tu.setName("a");
System.out.println(stu.getName());
}
}

运行结果

a

可以发现子类Student并没有定义任何操作,在主类中进行的所有操作都是Persion类中定义的。
说明:子类即使不扩充父类,也能维持父类的操作

在子类中扩充父类的功能

1
class 子类 extends 父类{}

直接继承不扩充内容

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
class Persion{
private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}
}

class Student extends Persion{
private String school;

public void setSchool(String school){
this.school = school;
}

public String getSchool(){
return school;
}
}

public class ExtendsTest{
public static void main(Strin args []){
Student stu = new Student(); //实例化的是Student类
stu.setName("a"); //Persion类中定义的
stu.setSchool("123") //Student类中定义的
System.out.println(stu.getName() + " " + stu.getSchool);
}
}

结果

a 123

以上的代码,子类对于父类的功能进行了扩充(扩充了一个属性和两个方法)。但是思考一下:子类从外表看是扩充了父类的功能,但是对于以上的代码,子类还有一个特点:子类实际上是将父类定义的更加的具体化的一种手段。父类表示的范围大,而子类表示的范围小。

继承的限制

  • 限制一

在一个子类继承的时候,实际上会继承父类之中的所有操作(属性、方法),但是需要注意的是,对于所有的非私有(no private)操作属于显式继承(可以直接利用对象操作),而所有的私有操作属于隐式继承(间接完成)

栗子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Persion{
private String name;

public void setName(String name){
this.name = name;
}

public String getName(){
return name;
}
}

class Student extends Persion{
System.out.println(name); //此次会发生错误,因为name被定义为private,不可见
}

public class ExtendsTest{
public static void main(Strin args []){
Student stu = new Student(); //实例化的是Student类
stu.setName("a"); //Persion类中定义的
}
}

对于Persion中name这个私有属性无法访问,但是可以通过set或get方法简介访问

  • 限制二

在继承关系之中,如果要实例化子类对象,会默认先调用父类构造,为父类之中的属性初始化,之后再调用子类构造,为子类之中的属性初始化,即:默认情况下,子类会找到父类之中的无参构造方法。

栗子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Persion{
public Persion(){
System.out.println("aaa");
}
}

class Student extends Persion{
public Student(){
System.out.println("bbb");
}
}

public class ExtendsTest{
public static void main(Strin args []){
Student stu = new Student();
}
}

结果

aaa
bbb

这个时候虽然实例化的是子类对象,但是发现它会默认先执行父类构造,调用父类构造的方法体执行,而后再实例化子类对象,调用子类的构造方法。而这个时候,对于子类的构造而言,就相当于隐含了一个super()的形式:

1
2
3
4
5
6
class Student extends Persion{
public Student(){
super();
System.out.println("bbb");
}
}

现在默认调用的是无参构造,而如果这个时候父类没有无参构造,则子类必须通过super()调用指定参数的构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Persion{
public Persion(String msg){
System.out.println("aaa");
}
}

class Student extends Persion{
public Student(){
super("hello");
System.out.println("bbb");
}
}

public class ExtendsTest{
public static void main(Strin args []){
Student stu = new Student();
}
}

结果

aaa
bbb

在任何的情况下,子类都逃不出父类构造的调用,很明显,super调用父类构造,这个语法和this()很相似:super调用父类构造时,一定要放在构造方法的首行

参考资料

Java 继承(extends)详解

本文作者 : Plain
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接 : https://plain-dev.com/java-extends/

本文最后更新于 天前,文中所描述的信息可能已发生改变