[Java]重学Java-继承

复用

随着码代码的时间增长,程序员会越发需要"复用"这个能力,比如最简单的对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->子类的构造器.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • 父类与子类 在Java术语中,如果C1类扩展自另一个类C2,我们称C2为父类,也称超类或基类,称C1为子类,也称次...
    Steven1997阅读 1,165评论 1 2
  • 5继承 5.1 类、超类和子类 重用部分代码,并保留所有域。“is-a”关系,用extends表示。 已存在的类被...
    我快要上天啦阅读 774评论 1 3
  • 继承已存在的类就是复用(继承)这些类的方法和域。在此基础上,还可以添加一些新的方法和域,以满足新的需求。 类、超类...
    Dcl_Snow阅读 401评论 0 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,621评论 18 399
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,051评论 0 4