Java核心技术第五章——1.类、超类、子类(1)

1.定义子类:
关键字extends表明正在构造的新类派生与一个已存在的类。已存在的类称为超类、基类或父类;新类称为子类、派生类或孩子类。超类和子类是Java程序员最常用的两个术语(emmm~~我觉得是叫父类比超类多)。

父类Employee

public class Employee {

    private String name;
    private double salary;
    private LocalDate hireDay;

    public Employee(String name, double salary,int year, int month, int day) {
        this.name = name;
        this.salary = salary;
        this.hireDay = LocalDate.of(year,month,day);
    }
}

子类Manager,通过extends关键字继承父类Employee

public class Manager extends Employee{

    //奖金
    private double bonus;


    public Manager(String name, double salary, int year, int month, int day) {
        super(name, salary, year, month, day);
        this.bonus = 0;
    }
    
}

在通过扩展超类定义子类的时候,仅需要指出子类与超类的不同之处。因此在设计类的时候,应该将通用的方法放在超类中,而将具有特殊用途的方法放在子类中,这种将通用的功能放到超类的做法,在面向对象程序设计中十分普遍。

2.覆盖方法:超类中有些方法对子类并不一定使用。例如Employee(员工)类的getSalary返回薪水的方法并不使用于Manager(经理)类的返回薪水的方法。为此,需要提供一个新的方法来覆盖超类中的这个方法。
Employee的返回薪水方法如下:

public double getSalary() {
        return salary;
    }

Manager覆盖Employee返回薪水的方法如下:

public double getSalary(){
        double baseSalary = super.getSalary();
        return baseSalary + bonus;//基本工资 + 奖金
    }

注意:super只是一个指示编译器调用超类方法的特殊关键字。

在子类中可以增加域、增加方法或覆盖超类的方法,然而绝对不能删除继承的任何域和方法。

3.子类构造器:如果子类的构造器没有显示地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中又没有显示地调用超类的其他带参数的构造器,则Java编译器将报告错误。

public class Employee {

    private String name;
    private double salary;
    private LocalDate hireDay;

    public Employee(String name, double salary,int year, int month, int day) {//父类的带参构造器
        this.name = name;
        this.salary = salary;
        this.hireDay = LocalDate.of(year,month,day);
    }

    public double getSalary() {
        return salary;
    }

}
public class Manager extends Employee{

    //奖金
    private double bonus;


    public Manager(String name, double salary, int year, int month, int day) {
        super(name, salary, year, month, day);//子类显示调用父类的带参构造器。
        this.bonus = 0;
    }

    //设置奖金
    public void setBonus(double bonus){
        this.bonus = bonus;
    }

}

4.继承层次:由一个公共超类派生出来的所有类的集合被称为继承层次。在继承层次中,从某个特定的类到其祖先类的路径被称为该类的继承链。

5.多态在Java程序设计语言中,对象的变量是多态的。一个Employee变量既可以引用一个Employee类对象,也可以引用一个Employee类的任何一个子类对象,例如:

Employee e = new Employee();
        Employee m1 = new Manager();
        Manager m2 = new Manager();

在上面的例子中,m2.setBonus(5000)是可以调用的,而m1.setBonus(5000)是不能调用的。

即使m1引用的对象是Manager,但是m1的声明类型是Employee,而setBonus方法并不是Employee类的方法。所以不能调用。

m1.setBonus(5000);//编译错误
        m2.setBonus(5000);

在Employee m1 = new Manager();这样的引用叫做向上转型。即子类的引用指向父类。那么就只能使用父类的属性和方法。那么问题来了,如果向上转型后子类的引用都调用不了自己的方法了,那咋办?在子类定义的方法怎么办?

此时就要重写方法了。就是我上面所说的第二小节覆盖方法,即使向上转型了,也可使用父类的方法和子类的方法。

Employee类的messager方法

public void messager(){
        System.out.println("我是Employee");
    }

Manager类的messager方法

public void messager(){
        System.out.println("我是Manager");
    }

测试

Employee e = new Employee();
        Employee m1 = new Manager();

        e.messager();
        m1.messager();

结果

我是Employee
我是Manager

总结一下Java多态的必要条件,有三个:

1.继承:在多态中必须存在继承的关系

2.重写:子类重写父类的方法。那么在调用其方法时才会调用到子类的方法。

3.向上转型:子类的引用指向父类。只有这样才可以调用父类的方法(没有被重写的方法)和子类的方法(被子类重写的方法)

欢迎大家在评论区指出不足之处 ~Thanks♪(・ω・)ノ