原文: https://beginnersbook.com/2013/03/inheritance-in-java/

一个类获取另一个类的属性(数据成员)和功能(方法)的过程称为继承。继承的目的是提供代码的可重用性,以便类只需要编写唯一的特性,其余的公共属性和功能可以从另一个类扩展。

子类:

扩展另一个类的特性的类称为子类,子类或派生类。

父类:

其属性和功能由另一个类使用(继承)的类称为父类,超类或基类。

继承是通过扩展其公共数据成员和方法,基于现有类定义新类的过程。

继承允许我们重用代码,它提高了 java 应用的可重用性。

注意:继承的最大优势是,基类中已经存在的代码不需要在子类中重写。

这意味着父类的数据成员(实例变量)和方法可以在子类中使用。

如果您发现很难理解什么是类和对象,那么请参考我在面向对象编程上分享的指南:OOP 概念

让我们回到主题:

语法:Java 中的继承

要继承一个类,我们使用extends关键字。这里的类XYZ是子类,类ABC是父类。XYZ类继承了ABC类的属性和方法。

  1. class XYZ extends ABC
  2. {
  3. }

继承示例

在这个例子中,我们有一个基类Teacher和一个子类PhysicsTeacher。由于类PhysicsTeacher扩展了基类的designationcollegeName属性以及does()方法,我们不需要在子类中声明这些属性和方法。

这里我们有collegeNamedesignationdoes()方法,这些方法对于所有老师都是通用的,所以我们在基类中声明了它们,这样像MathTeacherMusicTeacherPhysicsTeacher这样的子类不会需要编写此代码,可以直接从基类中使用。

  1. class Teacher {
  2. String designation = "Teacher";
  3. String collegeName = "Beginnersbook";
  4. void does(){
  5. System.out.println("Teaching");
  6. }
  7. }
  8. public class PhysicsTeacher extends Teacher{
  9. String mainSubject = "Physics";
  10. public static void main(String args[]){
  11. PhysicsTeacher obj = new PhysicsTeacher();
  12. System.out.println(obj.collegeName);
  13. System.out.println(obj.designation);
  14. System.out.println(obj.mainSubject);
  15. obj.does();
  16. }
  17. }

输出:

  1. Beginnersbook
  2. Teacher
  3. Physics
  4. Teaching

基于上述例子,我们可以说PhysicsTeacher IS-A Teacher。这意味着子类与父类具有 IS-A 关系。这是继承被称为子类和父类之间的 IS-A 关系

注意:

派生类继承声明为publicprotected的所有成员和方法。如果超类的成员或方法声明为private,则派生类不能直接使用它们。私有成员只能在自己的类中访问。只能使用公共或受保护的超类获取器和设置器方法访问此类私有成员,如下例所示。

  1. class Teacher {
  2. private String designation = "Teacher";
  3. private String collegeName = "Beginnersbook";
  4. public String getDesignation() {
  5. return designation;
  6. }
  7. protected void setDesignation(String designation) {
  8. this.designation = designation;
  9. }
  10. protected String getCollegeName() {
  11. return collegeName;
  12. }
  13. protected void setCollegeName(String collegeName) {
  14. this.collegeName = collegeName;
  15. }
  16. void does(){
  17. System.out.println("Teaching");
  18. }
  19. }
  20. public class JavaExample extends Teacher{
  21. String mainSubject = "Physics";
  22. public static void main(String args[]){
  23. JavaExample obj = new JavaExample();
  24. /* Note: we are not accessing the data members
  25. * directly we are using public getter method
  26. * to access the private members of parent class
  27. */
  28. System.out.println(obj.getCollegeName());
  29. System.out.println(obj.getDesignation());
  30. System.out.println(obj.mainSubject);
  31. obj.does();
  32. }
  33. }

输出是:

  1. Beginnersbook
  2. Teacher
  3. Physics
  4. Teaching

在上面的例子中需要注意的重要一点是,子类能够通过父类的受保护方法访问父类的私有成员。当我们创建一个实例变量(数据成员)或方法受保护时,这意味着它们只能在类本身和子类中访问。这些公共,受保护,私有等都是访问说明符,我们将在接下来的教程中讨论它们。

继承的类型

要详细了解继承类型,请参阅: Java 中的继承类型

单一继承:指的是一个子类和父类关系,其中一个类扩展另一个类。

Java 编程中的继承 - 图1

多级继承:指一个类扩展子类的子类和父类关系。例如,C类扩展了B类,B类扩展了A类。

Java 编程中的继承 - 图2

分层继承:指的是子类和父类关系,其中多个类扩展同一个类。例如,BCB类。D扩展了相同的A类。

Java 编程中的继承 - 图3

多重继承 :指一个类扩展多个类的概念,这意味着子类有两个父类。例如,类C扩展了类AB. Java 不支持多重继承,请阅读多重继承

Java 编程中的继承 - 图4

混合继承:在单个程序中组合多种类型的继承。例如A类和A类。B扩展了类C,另一个类D扩展了类A,然后这是一个混合继承示例,因为它是单继承和层次继承的组合。

构造函数和继承

当我们创建子类的对象时,会调用子类的构造函数,它默认调用超类的默认构造函数。因此,在继承中,对象是自上而下构造的。可以使用super关键字显式调用超类构造函数,但它应该是构造函数中的第一个语句。super关键字指的是超类,紧接在层次结构中的调用类之上。不允许使用多个super关键字来访问除直接父级之外的祖先类。

  1. class ParentClass{
  2. //Parent class constructor
  3. ParentClass(){
  4. System.out.println("Constructor of Parent");
  5. }
  6. }
  7. class JavaExample extends ParentClass{
  8. JavaExample(){
  9. /* It by default invokes the constructor of parent class
  10. * You can use super() to call the constructor of parent.
  11. * It should be the first statement in the child class
  12. * constructor, you can also call the parameterized constructor
  13. * of parent class by using super like this: super(10), now
  14. * this will invoke the parameterized constructor of int arg
  15. */
  16. System.out.println("Constructor of Child");
  17. }
  18. public static void main(String args[]){
  19. //Creating the object of child class
  20. new JavaExample();
  21. }
  22. }

输出:

  1. Constructor of Parent
  2. Constructor of Child

继承和方法覆盖

当我们在父类中已经存在的子类中声明相同的方法时,这称为方法覆盖。在这种情况下,当我们从子类对象调用该方法时,将调用该方法的子类版本。但是我们可以使用super关键字调用父类方法,如下例所示:

  1. class ParentClass{
  2. //Parent class constructor
  3. ParentClass(){
  4. System.out.println("Constructor of Parent");
  5. }
  6. void disp(){
  7. System.out.println("Parent Method");
  8. }
  9. }
  10. class JavaExample extends ParentClass{
  11. JavaExample(){
  12. System.out.println("Constructor of Child");
  13. }
  14. void disp(){
  15. System.out.println("Child Method");
  16. //Calling the disp() method of parent class
  17. super.disp();
  18. }
  19. public static void main(String args[]){
  20. //Creating the object of child class
  21. JavaExample obj = new JavaExample();
  22. obj.disp();
  23. }
  24. }

输出是:

  1. Constructor of Parent
  2. Constructor of Child
  3. Child Method
  4. Parent Method