美文网首页Java
[Java]重学Java-继承

[Java]重学Java-继承

作者: AbstractCulture | 来源:发表于2021-06-08 20:33 被阅读0次

复用

随着码代码的时间增长,程序员会越发需要"复用"这个能力,比如最简单的对String类进行判空:

 str == null || "".equals(str);

我们需要每次都这样写么?在面向对象中,我们可以利用类来封装这块逻辑进行复用。
现在,我们来思考:
除了方法,能否基于类的层面进行复用呢,当许多的对象都拥有相同的状态,我们是否可以用一个基类来对这些属性进行抽象?
答案是可以的,Java可以利用“继承”(Inheritance)的方式对类进行复用,只需要一个extends即可获取父类的能力(包括方法与属性)。

使用继承

UML

UML

编写Employee的子类Manager

  • com.tea.modules.model.base.Employee
package com.tea.modules.model.base;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

/**
 * com.tea.modules.model.base <br>
 * 雇员类
 *
 * @author jaymin
 * @since 2021/5/25
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    /**
     * 名称
     */
    private String name;
    /**
     * 工资
     */
    private double salary;
    /**
     * 入职日期
     */
    private LocalDate hireDay;

    /**
     * 涨工资
     * @param byPercent 涨薪幅度,例如: 1.25
     */
    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary *= raise;
    }
}

这是一个基类-Employee,有三个成员属性: name,salary,hireDay,提供了一个涨工资的方法: raiseSalary.

  • com.tea.modules.model.po.Manager

现在我们需要创建一个经理类用来直接继承Employee:
经理类,继承自雇员。经理属于特殊的雇员:
除了领工资外,经理还可以达到绩效后领取奖金

package com.tea.modules.model.po;

import com.tea.modules.model.base.Employee;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.time.LocalDate;

/**
 * com.tea.modules.model.po <br>
 * 经理类,继承自雇员。经理属于特殊的雇员:<br>
 * 除了领工资外,经理还可以达到绩效后领取奖金 <br>
 * Employee->超类(super class)|基类(base class)|父类(parent class)<br>
 * Manager->子类(sub class)|派生类(derived class)|孩子类(child class) <br>
 *
 * @author jaymin
 * @since 2021/5/25
 */
@Data
@NoArgsConstructor
@ToString(callSuper = true)
public class Manager extends Employee {
    /**
     * 奖金
     */
    private double bonus;

    public Manager(String name, double salary, LocalDate hireDay, double bonus) {
        super(name, salary, hireDay);
        this.bonus = bonus;
    }

    /**
     * 经理的工资由[工资+奖金]组成
     *
     * @return double
     */
    @Override
    public double getSalary() {
        // 注意这里要使用super关键字,否则会无限递归
        double baseSalary = super.getSalary();
        return baseSalary + bonus;
    }
}

Employee->超类(super class)|基类(base class)|父类(parent class)
Manager->子类(sub class)|派生类(derived class)|孩子类(child class)

  • Demo
package com.tea.modules.java8.extend;

import com.tea.modules.model.base.Employee;
import com.tea.modules.model.po.Manager;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * com.tea.modules.java8.extend <br>
 * 理解继承
 *
 * @author jaymin
 * @since 2021/5/25
 */
public class ManagerDemo {

    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        LocalDate hireDay = LocalDate.of(2021, 5, 25);
        Employee manager = new Manager("经理", 20000, hireDay, 10000);
        Employee jack = new Employee("Jack", 10000, hireDay);
        Employee james = new Employee("James", 10000, hireDay);
        employees.add(manager);
        employees.add(jack);
        employees.add(james);
        employees.forEach(System.out::println);
    }
}
  • Result
Manager(super=Employee(name=经理, salary=30000.0, hireDay=2021-05-25), bonus=10000.0)
Employee(name=Jack, salary=10000.0, hireDay=2021-05-25)
Employee(name=James, salary=10000.0, hireDay=2021-05-25)

多态

在最后一句employees.forEach(System.out::println);中:
对于Manager类型的manger引用,调用的是Manager类的toString(不仅打印了自己的信息,还打印了父类的信息).
对于Employee类型的jack引用,调用的是Employee类的toString.
这个过程由虚拟机来控制,可以用一个变量来表示多种实际类型的现象称为多态(polymorphism),在运行时可以自动选择调用哪个方法的现象叫做动态绑定(dynamic bingding).

  • 子类赋值给超类变量
 Employee manager = new Manager("经理", 20000, hireDay, 10000);

反之则无效,无法用Manager去接收一个Employee变量.

单一继承原则

java只支持单一继承,不支持同时继承多个类。但是你可以多层级继承,如图所示:

单一继承

方法调用

方法调用

再聊final

被final修饰的变量不可变,同样,被final修饰的类或者方法也是不可以被扩展和重写的。某种意义上来说,被final修饰的方法就像被"锁"住了一样.

这个特性比较重要,在后面的Spring框架中,我们会了解到,被final修饰的方法使用CGLIB是无法做增强的.

类型转换

这里我们创建了List<Employee>的列表,里面既存放了Employee类型的对象,也有Manager类型的对象.那么我们需要用到Manager的方法时,就需要用到类型强制转换了

public static void main(String[] args) {
    List<Employee> employees = new ArrayList<>();
    LocalDate hireDay = LocalDate.of(2021, 5, 25);
    Employee manager = new Manager("经理", 20000, hireDay, 10000);
    Employee jack = new Employee("Jack", 10000, hireDay);
    Employee james = new Employee("James", 10000, hireDay);
    employees.add(manager);
    employees.add(jack);
    employees.add(james);
    // 类型强制转换
    for (Employee employee : employees) {
        if(employee instanceof Manager){
            Manager managerPerson = (Manager) employee;
            System.out.println(managerPerson.getSalary());
        }
    }
}

Object

所有的Java对象都继承自Object类,也就是说,你可以用Object接收任意类型的对象。在Object中,包含了8个方法,下面我们来简单了解一下:

  • equals
    Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,比较的是两个对象的引用值是否一致。但通常情况,我们都需要重写equals,来比较两个对象的状态是否一致。
public boolean equals(Object obj) {
    return (this == obj);
}
  • getClass
    返回此 Object 的运行时类。返回的 Class 对象是被表示的类的静态同步方法锁定的对象
  • hashCode
    返回对象的哈希码值。
    关于hashCode有以下规定:
    对于同一个对象,多次调用hashCode必须返回相同的整数.
    equals方法比较相等,hashCode返回值必须相等.
    equals方法比较不相等,hashCode可以相等也可以不等.
  • toString
    toString返回对象值的字符串,在平时开发中,应该始终覆盖toString方法,否则只会打印引用信息,无法查看对象的状态。

数组toString推荐使用Arrays.toString(array);
剩下的方法,在后面的章节进行讲解.

加载具有继承关系的对象

父类的static->父类构造器->子类的static->子类的构造器.

相关文章

  • [Java]重学Java-继承

    复用 随着码代码的时间增长,程序员会越发需要"复用"这个能力,比如最简单的对String类进行判空: 我们需要每次...

  • Hello Java

    目录 Java-基础(1/6) Java-对象(2/6) Java-核心库类 上(3/6) Java-核心库类下(...

  • [Java]重学Java-集合

    容器 很多时候,我们写程序需要进行批量的操作,比如说,新增一批学生列表.那么就需要有容器来装下这10个对象。Jav...

  • [Java]重学Java-接口

    接口是什么 首先接口不是类,它本身是无法被实例化的,只有实现类可以被实例化。它更像是一种功能的描述,程序输入什么值...

  • [Java]重学Java-多态

    从一个例子理解多态 对于一个不同特征的对象,使用接口可以隐藏子类的行为,对外暴露同一个接口,从而实现编程的解耦. ...

  • Java-继承

    继承 继承(inheritance)是面向对象的重要概念。继承是除组合(composition)之外,提高代码重复...

  • [Java]重学Java-可变参数

    可以变动的参数数量 编程离不开写方法(函数),Java中的大多数方法都是固定数量的参数,JDK5提供了可变参数来让...

  • [Java]重学Java-枚举类

    枚举可以做什么 假设我们现在想表达星期,为了避免魔法值的出现,我们可能会写一个常量类: 这样一来,1-7的星期数就...

  • [Java]重学Java-内部类

    什么是内部类 一个类中定义了另一个类,被定义的类叫作内部类。内部类可以将逻辑隐藏,使用好修饰符可以让实现逻辑对外隔...

  • [Java]重学Java-文档注释

    文档注释 刚开始学习Java的时候,觉得注释是很啰嗦的东西,但是随着编码的时间增长,觉得注释是很重要的东西。写好注...

网友评论

    本文标题:[Java]重学Java-继承

    本文链接:https://www.haomeiwen.com/subject/wlxteltx.html