Java——继承

继承

本文首发于个人博客——然Coder
在之前讨论过接口这种面向对象的特性,这里我们来看看另一个面向对象的特性——继承。

继承,是在现有的类的基础上派生出另一个类,他可以从现有类中继承得到(或者叫重用)方法,并且还可以再原有的基础上进行适当扩展方法和域。

父类与子类

我们定义一个 Employee类,将其作为公司中所有员工的父类:该类是其他所有员工的基础信息类,不同员工有不同的属性和行为。

public class Employee {
    public String ID;
    public String name;
    public Date enterTime;
    public int status;
    public Employee() {}

    public Employee(String ID, String name, Date enterTime, int status) {
        this.ID = ID;
        this.name = name;
        this.enterTime = enterTime;
        this.status = status;
    }

    public boolean checkedIn() {
        System.out.println("员工打卡上班。");
        return true;
    }

    public boolean checkedOut() {
        System.out.println("员工打卡下班。");
        return true;
    }
}

现在我们建立一个经理类 Manager类,让其继承 Employee类,该类就叫做 Employee的子类。

import java.util.Date;
public class Manager extends Employee {
    public String departmentID;
    public int level;
    public Manager(String ID, String name, Date enterTime, int status) {
        super(ID, name, enterTime, status);
    }

    public void setDepartmentID(String departmentID) {
        this.departmentID = departmentID;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public static void main(String[] args) {
        Manager boss = new Manager("1","Jason",new Date(),1);
        System.out.println(boss.ID);
    }
}

定义和继承子类方法

从上述的代码可以清晰地看出,在子类 Manager中我们添加了两个其他的字段 : departmentIDlevel,用来存储经理特有的属性,同样我们也可以增加 Manager特有的行为,比如安排工作等:

public void arrangeWork(Employee employee) {
    System.out.println("为" + employee.name + "安排工作。");
}

另外,他本身也还是具有父类 Employee中的非私有方法的,比如上下班打卡的方法,子类可以选择继承继续使用父类的实现,也可以自己重写覆盖父类的方法。

@Override
public boolean checkedIn() {
    System.out.println("经理上班打卡。");
    return true;
}

@Override
public boolean checkedOut() {
    System.out.println("经理下班打卡。");
    return true;
    //or super.checkedOut();
}

在覆盖重写父类的方法时,也可以通过 super关键字来调用父类的方法来辅助实现。

不同于 thissuper不是对象的引用,而是绕过动态查找方法并调用特定方法的指令。

在进行父类方法覆盖的时候,应当注意方法名以及参数列表是不能更改的,返回值类型,可以用父类返回值的子类代替。

注意

覆盖一个方法的时候,子类方法与父类方法的可见性应当是至少一致的,当父类的方法声明为 public时,在子类中如果要覆盖该方法,就需要也将方法 声明为 public,如果漏掉,编译器会提示访问权限变弱。

子类的构造

在之前的代码中,我们为 Manager类提供了一个构造方法,用于构造一个 Manager对象:

public String departmentID;
public int level;
public Manager(String ID, String name, Date enterTime, int status) {
    super(ID, name, enterTime, status);
}

这里我调用了父类的构造方法,注意到, Manager本身还有其他 Employee不具有的属性,如果我们需要将该系列的属性赋初值,只需要在调用了父类的构造方法后,继续赋值就可以了:

父类的构造方法调用必须在构造方法中的第一条语句。

public Manager(String ID, String name, Date enterTime, int status, String departmentID, int level) {
    super(ID, name, enterTime, status);
    this.departmentID = departmentID;
    this.level = level;
}

父类赋值

Java中对一个父类赋予一个子类对象是合法的。

Employee employee = new Manager();

此时我们来调用 checkedIn()方法:employee.checkedIn(),是调用父类的方法还是子类的方法?

事实上,是会调用子类的方法。原因是 JVM的动态方法寻找。

在调用方法时, JVM会查看对象的实际类型,并且定位方法的版本,这个过程叫做 动态方法寻找

final方法和类

final即为最终的意思,就是说它是最终的版本,不允许修改。

当一个类被声明为 final后,将不允许有继承他;同样,一个类的方法被声明为 final后也将不允许子类修改覆盖它。

抽象方法和类

一个类可以定义没有实现的方法,并且啊,强迫子类去实现,这样的方法和类就属于抽象方法和抽象类,,必须用 abstract关键字修饰。

任何继承自抽象类的子类要么实现所有没有实现的方法,要么自己也声明为抽象类。

不同于接口,抽象类可以拥有实例变量和构造函数

和接口类似,抽象类不可能拥有本身的实例对象

欢迎关注

个人微信公众号【然Coder】
本文首发于个人博客
在这里插入图片描述

你可能感兴趣的:(java学习)