Java从入门到放弃(二十三):继承(上)

在面向对象编程(OOP)中,继承是一个核心概念,它允许我们创建一个新类(子类)来继承另一个类(父类)的属性和方法。这样做的好处是可以避免代码的重复,同时还可以扩展或修改继承来的行为和属性。

在前面的章节中,我们已经定义了Person类:

  1. class Person {
  2. private String name;
  3. private int age;
  4. public String getName() {...}
  5. public void setName(String name) {...}
  6. public int getAge() {...}
  7. public void setAge(int age) {...}
  8. }

现在,假设需要定义一个Student类。通过使用继承,我们可以在 Student 类中直接继承 Person 类的所有字段和方法,而无需再次定义 nameage 这两个字段及其方法。这样,Student 类的实例将自动拥有 Person 类的所有功能,并且还具备了 Student 类特有的 score 属性。

下面是使用继承后的 Student 类的代码示例:

  1. class Person {
  2. private String name;
  3. private int age;
  4. // 构造器、getter和setter方法
  5. public Person(String name, int age) {
  6. this.name = name;
  7. this.age = age;
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setName(String name) {
  13. this.name = name;
  14. }
  15. public int getAge() {
  16. return age;
  17. }
  18. public void setAge(int age) {
  19. this.age = age;
  20. }
  21. }
  22. class Student extends Person {
  23. // 继承了Person类,不需要再次定义name和age字段及其方法
  24. private int score;
  25. // 构造器
  26. public Student(String name, int age, int score) {
  27. super(name, age); // 调用父类的构造器
  28. this.score = score;
  29. }
  30. // 新增score字段的getter和setter方法
  31. public int getScore() {
  32. return score;
  33. }
  34. public void setScore(int score) {
  35. this.score = score;
  36. }
  37. }

 注意:子类自动获得了父类的所有字段,严禁定义与父类重名的字段!

在OOP的术语中,我们把Person称为超类(super class),父类(parent class),基类(base class),把Student称为子类(subclass),扩展类(extended class)。

继承树

在Java中,每个类都有一个继承体系,这使得对象可以共享和扩展公共的属性和方法。当我们在定义一个类时,如果没有明确指定继承自哪个类,Java编译器会自动将其继承自Object类。这是因为Object是Java中所有类的根类,它位于继承树的最顶端。因此,除了Object类本身,所有的类都会继承自某个父类。

当我们创建Student类时,我们使用extends关键字明确指出它继承自Person类。这样,Student类不仅继承了Person类的属性和方法,还可以添加或修改自己的特定行为。Student类的实例将拥有Person类的所有功能,并且增加了自己的score属性。

同样的,如果我们定义一个Teacher类,它也可以继承自Person类。这样,Teacher类将继承Person类的所有属性和方法,并可以添加自己的特定属性和方法。这种继承关系形成了一个层次结构,其中Object位于顶端,Person是中间的父类,而StudentTeacher是子类。

protected

在Java中,继承有一些访问控制的限制。特别是,子类不能直接访问父类的private成员。这是因为private访问修饰符限制了成员的访问范围仅在定义它们的类内部。这种设计是为了保护封装性,防止外部对类内部实现的直接访问和修改。

为了解决这个问题,我们可以将Person类的nameage字段的访问修饰符从private改为protected。这样做之后,这些字段就可以被子类Student访问了,因为protected访问级别允许子类及其子类访问这些成员。

  1. class Person {
  2. protected String name; // 从private改为protected
  3. protected int age; // 从private改为protected
  4. }
  5. class Student extends Person {
  6. public String hello() {
  7. return "Hello, " + name; // 现在可以访问name字段
  8. }
  9. }

super

在Java编程语言中,super是一个特殊的关键字,它被用来表示当前对象的直接父类。这个关键字在子类中特别有用,因为它允许子类访问父类的属性、方法和构造方法。当子类需要引用父类的成员时,可以使用super.fieldName的形式来明确指出要访问的是父类的字段,尽管在很多情况下,直接使用字段名也能达到同样的效果,因为编译器会自动解析到父类的字段。

例如,下面的Student类继承自Person类,并在hello方法中通过super.name访问父类的name字段:

  1. class Student extends Person {
  2. public String hello() {
  3. return "Hello, " + super.name; // 访问父类的name字段
  4. }
  5. }

然而,有时候必须显式地使用super关键字,尤其是在构造方法中。构造方法的第一个语句必须是对父类构造方法的调用,这是为了确保父类的成员变量能够被正确初始化。如果子类构造方法没有显式地调用父类构造方法,编译器会自动插入super();,这时候会默认调用父类的无参数构造方法。

来看这个例子:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Student s = new Student("Xiao Ming", 12, 89);
  4. }
  5. }
  6. class Person {
  7. protected String name;
  8. protected int age;
  9. public Person(String name, int age) {
  10. this.name = name;
  11. this.age = age;
  12. }
  13. }
  14. class Student extends Person {
  15. protected int score;
  16. public Student(String name, int age, int score) {
  17. this.score = score;
  18. }
  19. }

代码示例中,Student类的构造方法没有显式调用Person类的构造方法,这将导致编译错误,因为Person类没有无参数的构造方法。编译器试图插入super();,但是找不到匹配的Person构造方法,所以编译失败。

为了解决这个问题,Student类的构造方法必须显式地调用Person类中存在的一个构造方法,并提供相应的参数:

  1. class Student extends Person {
  2. protected int score;
  3. public Student(String name, int age, int score) {
  4. super(name, age); // 正确调用Person类的构造方法
  5. this.score = score;
  6. }
  7. }

super关键字在子类构造方法中的使用是必要的,尤其是当父类没有默认构造方法时。此外,需要注意的是,子类不会继承父类的构造方法,子类默认的构造方法是编译器自动生成的,而不是从父类继承的。因此,子类必须显式地调用父类的构造方法来确保正确的初始化。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧

你有新的私信

请务必要查看您的私信哟~~

×