继承是面向对象的三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。继承是指在原有类的基础上,进行功能扩展,创建新的类型。
概念与作用
代码复用:继承能够避免重复编写代码。当多个类存在相同的属性和方法时,可将这些共性提取到父类,子类直接继承使用,减少代码冗余。
构建层次结构:可以构建出层次分明的类结构,清晰展现类之间的 “is - a” 关系,让代码更符合现实世界的逻辑,增强代码的可维护性与可扩展性。
实现多态:继承是实现多态的基础,借助父类引用指向子类对象,能在运行时动态调用子类方法,提升代码的灵活性。
继承的语法
使用 extends
关键字来实现继承。
class ParentClass {
// 父类的属性和方法
public void parentMethod() {
System.out.println("This is a method in the parent class.");
}
}
class ChildClass extends ParentClass {
// 子类可以添加自己的属性和方法
public void childMethod() {
System.out.println("This is a method in the child class.");
}
}
ChildClass 继承自 ParentClass,它可以使用 ParentClass 里的非私有属性和方法,同时还能添加自己特有的属性和方法。
访问父类成员
super 关键字:在子类里,可使用 super 关键字来访问父类的成员。例如,当子类重写父类方法后,若想调用父类的原方法,就可以用 super 关键字。
class Parent {
public void printMessage() {
System.out.println("Message from parent class");
}
}
class Child extends Parent {
@Override
public void printMessage() {
super.printMessage();
System.out.println("Message from child class");
}
}
构造函数:子类的构造函数会默认调用父类的无参构造函数。若父类没有无参构造函数,子类的构造函数就需要使用 super 关键字显式调用父类的有参构造函数。
class Parent {
private int value;
public Parent(int value) {
this.value = value;
}
}
class Child extends Parent {
public Child(int value) {
super(value);
}
}
方法重写
定义:子类可以重写父类的方法,也就是在子类中定义一个和父类方法签名(方法名、参数列表、返回类型)相同的方法。重写后的方法会在调用时覆盖父类的方法。
规则:重写方法的访问权限不能比父类方法更严格,返回类型必须和父类方法的返回类型相同或者是其子类型。
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
继承的限制
单继承:在 Java 里,一个类只能有一个直接的父类,也就是单继承。不过,一个类可以实现多个接口,以此实现类似多继承的功能。
访问权限:子类无法直接访问父类的私有成员(私有属性和私有方法),只能通过父类提供的公共方法间接访问。
示例代码
employee类:
package inheritance;
import java.time.LocalDate;
public class Employee {
private String name;
private double salary;
private LocalDate hireDay;
public Employee(String name, double salary, int year, int month, int day) {
super();
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary(double byPercent) {
double raise=salary*byPercent/10;
salary+=raise;
}
}
manger类:
package inheritance;
public class Manger extends Employee{
private double bonus;
public Manger(String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
bonus=0;
}
public double getSalary()
{
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
public void setBonus(double b){
bonus=b;
}
}
test类:
package inheritance;
public class MangerTest {
public static void main(String[] args) {
Manger boss=new Manger("Carl Cracker", 80000, 1987, 12, 15);
boss.setBonus(5000);
Employee[] staff=new Employee[3];
staff[0]=boss;
staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15);
// print out information about all Employee objects
for (Employee e : staff)
System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());
}
}