Java中的继承是指子类继承或获取父类的所有非私有属性和行为的能力。继承是面向对象编程的四大支柱之一,用于提高层次结构中类之间的代码可重用性。
在本教程中,我们将了解 Java 支持的继承类型,以及在应用程序中如何实现继承。
在继承中,默认情况下,一个类扩展另一个类以继承其所有非私有成员。这个类称为子类或子类。子类从中扩展的类称为父类或超类。
在 Java 中,extends 关键字用于类之间的继承。
public class Parent {
}
public class Child extends Parent { //Child class is extending the Parent class
}
假设我们有 Employee
类。 Employee 类具有组织内所有员工都必须具有的一些属性和方法。
在同一个应用程序中,还可以有其他特殊员工,例如Manager
。经理是组织的正式员工,但除此之外,他们比其他员工(例如,下属或下属)具有更多的属性。
public class Employee {
private Long id;
private String firstName;
private String lastName;
//Getters and Setters
}
public class Manager extends Employee {
private List<Employee> subordinates;
public Manager(long id, String firstName, String lastName, List<Employee> subordinates) {
super(id, firstName, lastName);
this.subordinates = subordinates;
}
}
在上面的实现中,employees 具有共同的属性,如 id
、firstName
和 lastName
;而 manager 只有专门的 subordinates
属性。要继承 Employee
类的所有非私有成员(在本例中为 getter 和 setter 方法),Manager 扩展了 Employee 类。
让我们验证 Manager 类也继承了 Employee 属性。
Manager manager = new Manager(1l, "Lokesh", "Gupta", List.of(new Employee(2l, "Alex", "Dave")));
System.out.println(manager);
程序输出。
Manager{id=1, firstName='Lokesh', lastName='Gupta', subordinates=[Employee{id=2, firstName='Alex', lastName='Dave'}]}
显然,Manager 类能够使用 Employee 类的字段和方法。
现在考虑我们是否不使用继承。然后我们将在两个类中维护 id、firstName 和 lastName 字段。它会导致代码重复,这总是在代码维护中造成问题。
在 Java 中,继承可以是四种类型中的一种——取决于类层次结构。
在单继承中,一个子类扩展一个父类。上面的示例代码(Employee 和Manager)是单继承的示例。
在多级继承中,三个以上的类之间会有继承,一个子类作为另一个子类的父类。用一张图来理解吧。
在上面的示例中,B 类扩展了 A 类,因此 B 类是 A 类的子类。但是 C 扩展了 B,因此 B 是 C
的父类。所以 B
既是父类又是子类。
在层次继承中,只有一个超类,多个子类扩展超类。
这些子类B
、C
、D
将共享继承自$$$,但他们不会知道彼此的成员。
在多重继承中,一个子类可以继承多个父类的行为。
在图中,类D扩展了类A和B。这样,D就可以继承这两个类的非私有成员。但是,在 Java 中,我们不能对两个类使用 extends 关键字。那么,多重继承将如何工作?
直到 JDK 1.7,多重继承在 java 中是不可能的。但是从 JDK 1.8 开始,多重继承可以通过使用具有默认方法的接口。
在子类中,我们可以访问父类的非私有成员。让我们看看如何访问单个成员。
父类的构造函数可以通过super
关键字调用。只有两条规则:
super()
调用必须从子类构造函数进行。super()
调用必须是构造函数中的第一条语句。public class Manager extends Employee {
public Manager() {
super(); //This must be first statement inside constructor
//Other statements
}
}
非私有成员字段可以在子类中继承。我们可以使用点运算符访问它们,例如manager.id
。这里的id
属性继承自父类Employee
。
私有成员字段 必须通过公共 getter 和setter 方法访问。
Manager manager = new Manager(...);
manager.getId();
manager.getFirstName();
manager.getLastName();
我们在处理父类和子类中的同名字段时一定要小心。请记住,成员字段不能被覆盖。具有相同名称的字段将对父类隐藏该字段——同时通过子类访问。
在这种情况下,将根据引用类型来决定访问的属性。例如,假设 Employee 和 Manager 具有共同属性 rating。当我们调用 manager.rating 时,接收到的值将由引用类型决定。
class Employee {
int rating = 100;
}
class Manager extends Employee {
int rating = 200;
}
Manager manager = new Manager();
System.out.println(manager.rating); //200
Employee mgrEmployee = new Manager();
System.out.println(mgrEmployee.rating); //100
在上面的示例中,即使我们两次都创建了 Manager 的实例,但是 rating 的值是不同的,因为它是从引用类型引用的。
子类可以使用 this 关键字直接访问父类的非私有方法。子类不能访问父类的私有方法。
在下面的示例中,Manager 类能够访问 toString() 方法中的公共 getter 和 setter 方法。
public class Manager extends Employee {
private List<Employee> subordinates;
@Override
public String toString() {
return "Manager{" +
"id=" + getId() +
", firstName='" + getFirstName() + '\'' +
", lastName='" + getLastName() + '\'' +
", subordinates=" + subordinates +
'}';
}
}
请注意,如果父类和子类具有同名的非私有方法,则访问的方法将来自实际实例类型。
class Employee {
public int getRating() {
return 100;
}
}
class Manager extends Employee {
public int getRating() {
return 200;
}
}
Manager manager = new Manager();
System.out.println(manager.getRating()); //200
Employee mgrEmployee = new Manager();
System.out.println(mgrEmployee.getRating()); //200
让我们总结一下我们在 Java 中学到的关于继承的知识:
extends
关键字实现的。如果您有任何问题,请在评论部分告诉我。
快乐学习!!
地址:https://www.cundage.com/article/java-inheritance.html