代码的认爹之路: 面向对象继承

2023-11-11

面向对象 - 继承

前言 :

​ Hello , 各位同学朋友大家好啊, 今天给大家分享的技术呢, 是面向对象三大特征之一的继承 .

我们今天主要按照以下几个点, 展开继承的讲解

目录 :

  • 继承的介绍

  • 继承的好处和弊端

  • 继承中成员访问特点 - 成员变量

  • 继承中成员访问特点 - 成员方法

    • 方法重写
  • 继承中成员访问特点 - 构造方法

  • this 和 super 关键字

1. 继承的介绍

​ 提到了继承, 大家想到了什么 ? 是的, 子女继承到的家产, 那家产是存在着一种关系的, 父亲和儿子的关系 .

​ 对比生活中的继承, Java 中的继承, 其实就是让类与类之间产生关系, 什么关系 ? 子父类关系, 当这种关系建立起来之后, 子类就可以直接使用父类中, 非私有的成员了.

​ 聊到这个地方, 很多同学就在想, 我为什么让我的类与类之间建立这种关系呢 ? 请同学们先阅读下方代码

​ 假设, 我要编写一款 xxx 公司的人员管理系统, 这款管理系统需要对项目经理和程序员的信息做管理, 所以就需要编写如下两个类

在这里插入图片描述

​ 现在大家可以发现, 这两个类中的东西, 完全是长一样的 !!! 那我将来要是再多一个 Hr 的类, 对人事的信息做管理, 这些重复的代码, 岂不是要再写一遍 ? 麻烦 !

​ 所以, 这时候我要用继承来优化代码了

​ 我将这些类当中, [共性] 或者说是 [相同] 的内容, 抽取到一个父类 (Employee 员工 ) 当中 , 再让 Coder 和 Manager 继承 Employee, 代码就不需要重复编写了 , 这就能够提高代码的复用性了 ~

在这里插入图片描述

​ 但是, 代码层面, 我给如何让 Coder 和 Manager 继承 Employee 呢 ? 请同学们继续看继承的格式

继承的格式 :

在这里插入图片描述

可以看到, 实现继承, 我们是通过 extends 关键字进行编写的 , 下面我们编写下代码

  • 示例代码 :
class Employee {
    String name;
    int age;
    double salary;
}

class Coder extends Employee {

}

class Manager extends Employee {

}

public class Test {
    public static void main(String[] args) {
        Coder c = new Coder();
        c.name = "张三";
        c.age = 23;
        c.salary = 12000;

        System.out.println(c.name + "---" + c.age + "---" + c.salary);

        Manager m = new Manager();
        m.name = "李四";
        m.age = 24;
        m.salary = 18000;

        System.out.println(m.name + "---" + m.age + "---" + m.salary);
    }
}

通过上面的代码, 同学们可以发现, Coder 和 Manager 中, 明明什么都没写, 但是却能够访问到父类 Employee 中的属性了

所以, 重复的代码就不需要重复编写, 代码的复用性就提高了 ~

但是, 我相信有些同学可能会想

Q : 按照标准 JavaBean 来说, 成员变量不应该私有化吗 ? 那如果父类中的成员私有了, 子类岂不是用不到这些数据了.

A : 能想到这个问题非常好, 说明之前的知识掌握的很扎实, 但是继续想, 我们私有成员变量之后, 会提供对应的 set 和 get 方法吧, 这些set \ get 可都是公共的, 子类是可以继承到直接用的

  • 示例代码 :
package com.itheima.myextends;


class Employee {
    private String name;
    private int age;
    private double salary;


    public Employee() {
    }

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

}

class Coder extends Employee {

}

class Manager extends Employee {

}

public class Test {
    public static void main(String[] args) {
        Coder c = new Coder();
        c.setName("张三");
        c.setAge(23);
        c.setSalary(12000);
        
        System.out.println(c.getName() + "---" + c.getAge() + "---" + c.getSalary());

        Manager m = new Manager();
        m.setName("李四");
        m.setAge(24);
        m.setSalary(18000);

        System.out.println(m.getName() + "---" + m.getAge() + "---" + m.getSalary());
    }
}

2. 继承的好处和弊端

好处 :

​ 通过上面的代码, 同学们感受到继承的什么好处了啊 ? 是的, 非常明显的发现, 代码的复用性提高了.

除此之外呢, 继承还可以提高代码的维护性 , 这什么意思 ?

​ 假设, 我要在这款管理系统中, 加入一个 id 的属性, 那使用继承前, 我就需要在每一个类中, 挨个编写, 但是现在有了继承后, 我只需要在父类中编写一个 id, 所有的子类, 是不是就都具备了这个属性了 ? 是的 ! 这就提高了代码的维护性了 !

在这里插入图片描述

弊端 :

​ 继续刚刚的思路, 同学们可能会想, 增加一个, 所有子类都有了, 那删除一个, 岂不是所有子类都没有了啊…

​ 这不就牵一发而动全身了嘛… 是的, 这就是继承的弊端, 类的耦合性太强了.

在这里插入图片描述

何时使用继承 :

聊到现在, 大家发现继承有好处, 也有弊端, 那该如何设计, 才能让利大于弊呢 ?

在这里插入图片描述

  • 正确示例 :

在这里插入图片描述

  • 错误示例 :

在这里插入图片描述

3. 继承中成员变量访问特点

  • 思考:子父类中,如果出现了重名的成员变量,使用的时候会优先使用??
    在这里插入图片描述

  • 运行效果 :

20
  • 原因 :

在这里插入图片描述

一定要使用父类的, 可以使用 super 关键字进行区分

这里同学们可以先建立起一个使用思路

  • this. 调用本类成员
  • super.调用父类成员
public class Zi extends Fu {
	int num = 20;
    
    public void method(){
    	System.out.println(super.num);
    }
}

在这里插入图片描述

4. 继承中成员方法访问特点

  • 思考:子类继承了父类之后,是否可以自己继续定义方法?

  • 回答:当然可以, 子类继承父类, 是可以在继承到父类成员之后, 继续加东西的

在这里插入图片描述

  • 问题 : 那子父类中, 要是出现了重名的成员, 逻辑却不一样呢 ?
public class Fu {
	public void method() {
       // 父类的方法
       System.out.println("父类method...");
    }
}

class Zi extends Fu {
    public void method() {
        System.out.println("子类method...");
    }
}
  • 运行结果 :
子类method...
  • 结论 :

    子父类中如果出现了重名的成员方法,优先使用子类的方法 , 但这其实是子类方法对父类方法进行了重写

方法重写 Override :

​ 先跟大家聊聊什么是方法重写,在继承体系中,子类可以继承到父类的方法, 但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改, 这就需要采用方法的重写,方法重写又称方法覆盖

在这里插入图片描述

class Fu {
	public void catch(){
		System.out.println("使用弓箭捉羊...");
	}
}

class Zi extends Fu {
	@Override 
	public void catch(){
		System.out.println("使用98Kar狙击枪捉羊...");
	}
}
  • 注意事项 :
    在这里插入图片描述

解释 :

父类中私有的方法, 子类访问不到, 就更不能重写了

子类重写父类方法, 可以理解为是对功能进行增强, 那如果允许把访问权限降低, 那岂不是功能越做越差了嘛

Java 中继承的特点 :

​ 了解了 Java 中方法重写后, 我们再来说下 Java 中继承的特点

  • 特点 : Java只支持单继承,不支持多继承,但支持多层继承

    • 其实就是说, 一个类, 最多只能有一个父类, 不能同时有多个父类
    class A {}
    
    class B {}
    
    class C extends A , B {}   // 编译出错
    
    • 为什么 ? 因为担心逻辑冲突

在这里插入图片描述

  • 问题 : 那多层继承呢 ?

5. 继承中构造方法的访问特点

  • 思考问题 : 父类的构造方法, 子类能不能继承到呢 ?

  • 回答 : 不允许, 因为构造方法要求, 方法名和类名必须相同, 如果子类继承到父类的构造方法, 那方法名和类名就不一致了

  • 结论 : 子类不能继承父类的构造方法, 将来子类的构造方法, 需要自己编写

public Fu {
	public Fu(){}
}

class Zi extends Fu {
	public Fu(){}   // 如果子类继承到父类的构造方法,  那方法名和类名就不一致了
}
继承中构造方法的访问流程
  • 阅读代码材料 :
public class Test {
    public static void main(String[] args) {
        Zi z1 = new Zi();
        Zi z2 = new Zi(10);
    }
}

class Fu {
    public Fu() {
        System.out.println("Fu类空参构造方法");
    }

    public Fu(int num) {
        System.out.println("Fu类带参数构造方法");
    }
}

class Zi extends Fu {

    public Zi() {
        System.out.println("Zi类空参数构造方法");
    }

    public Zi(int num) {
        System.out.println("Zi类带参数构造方法");
    }

}
  • 运行效果 :
Fu类空参构造方法
Zi类空参数构造方法
Fu类空参构造方法
Zi类带参数构造方法

通过打印效果同学们可以看出, 我们无论通过子类的哪一个构造方法创建对象, 都会执行到 Fu类的空参构造方法

为什么 ? 因为在子类的构造方法, 第一行代码, 系统会默认帮我们加入 super ();

通过super() 在访问父类的构造方法 , 现在我们手动把 super(); 加上, 同学们再阅读下试试吧~

public class Test {
    public static void main(String[] args) {
        Zi z1 = new Zi();
        Zi z2 = new Zi(10);
    }
}

class Fu {
    public Fu() {
        System.out.println("Fu类空参构造方法");
    }

    public Fu(int num) {
        System.out.println("Fu类带参数构造方法");
    }
}

class Zi extends Fu {

    public Zi() {
    	super();
        System.out.println("Zi类空参数构造方法");
    }

    public Zi(int num) {
    	super();
        System.out.println("Zi类带参数构造方法");
    }

}

okk, 看懂了执行流程之后, 新的问题来了, 我们知道学习这个细节, 对代码有什么帮助呢 ?

答案是 : 子类将来可以把一部分数据, 交给父类初始化了

我们来看一段代码

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class Student extends Person {
    private double score;

    public Student() {
    }

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public void study() {
        System.out.println(
                "姓名为" + super.getName()
                + ", 年龄为" + super.getAge()
                + ", 成绩为" + score + "分的学生, 正在学习Java");
    }
}

public class ExtendsTest2 {
    public static void main(String[] args) {
        Student stu = new Student("李四", 24, 100);
        stu.study();
    }
}

在上述代码中, 我们可以发现, main方法中 , 创建学生对象, 我们给了 3个参数, 先执行子类的带参数构造方法

其中前两个数据, 我们通过super, 交给了父类初始化, 最后一个成绩数据, 父类没有, 子类自己完成了初始化

public Student(String name, int age, double score) {	// "李四", 24, 100
        super(name, age);	// "李四", 24 交给父类
        this.score = score; // 100 子类自己初始化
}

配合一张内存图 , 大家再看一下

在这里插入图片描述

这里我们可以发现, 堆内存的对象中, 会存在一个 super 区域, 专门存放父类的成员

所以, 前两个数据, 父类中有, 就交给父类初始化, 最后一个数据, 父类没有, 子类就自己完成初始化.

6. this 和 super

上述文章中, 我们其实关于 this 和 super 做了很多使用了, 接下来我们来梳理下

  • this:代表本类对象的引用

  • super:代表父类存储空间的标识(可以理解为父类对象引用)

在这里插入图片描述

好啦, 本次关于继承的技术, 就跟大家聊到这里了

我们下次再见 ~

掰掰~ ()
ic Student(String name, int age, double score) { // “李四”, 24, 100
super(name, age); // “李四”, 24 交给父类
this.score = score; // 100 子类自己初始化
}




配合一张内存图 , 大家再看一下



[外链图片转存中...(img-goh6wlH8-1662548671221)]



这里我们可以发现,  堆内存的对象中,  会存在一个 super 区域,  专门存放父类的成员

所以,  前两个数据,  父类中有,  就交给父类初始化,  最后一个数据,  父类没有,  子类就自己完成初始化.



### 6. this 和 super



上述文章中,  我们其实关于 this 和 super 做了很多使用了,  接下来我们来梳理下



* **this**:代表本类对象的引用

* **super**:代表父类存储空间的标识(可以理解为父类对象引用)



[外链图片转存中...(img-WVEW74vC-1662548671222)]





好啦,  本次关于继承的技术,  就跟大家聊到这里了

我们下次再见 ~



掰掰~  (*^▽^*)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

代码的认爹之路: 面向对象继承 的相关文章

  • “_加载小部件时出现问题”消息

    加载小部件时 如果找不到资源或其他内容 则会显示 加载小部件时出现问题 就这样 惊人的 此消息保留在主屏幕上 甚至没有说明加载时遇到问题的小部件 我通过反复试验弄清楚了这一点 但我想知道发生这种情况时是否有任何地方可以找到错误消息 Andr
  • 添加动态数量的监听器(Spring JMS)

    我需要添加多个侦听器 如中所述application properties文件 就像下面这样 InTopics Sample QUT4 Sample T05 Sample T01 Sample JT7 注意 这个数字可以多一些 也可以少一些
  • 禁用 Eclipse Java 调试器的热代码替换 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在 Eclipse 中禁用热代码替换 https stackoverflow com questions 2594408 how do i disable hot code replace in
  • Grails 2.3.0 自动重新加载不起作用

    我最近将我们的项目升级到 grails 2 3 0 一切工作正常 除了每当我更改代码时自动重新加载都无法工作的问题 这包括所有项目工件 控制器 域 服务 gsps css 和 javascript 文件 我的旧版本 grails 可以正常工
  • 在文本文件中搜索单词并返回其频率

    如何在包含单词文本的文本文件中搜索特定单词并返回其频率或出现次数 使用扫描仪 String text Question how to search for a particular word in a text file containin
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • Firestore - RecycleView - 图像持有者

    我不知道如何编写图像的支架 我已经设置了 2 个文本 但我不知道图像的支架应该是什么样子 你能帮我告诉我图像的文字应该是什么样子才能正确显示吗 holder artistImage setImageResource model getArt
  • Java 8 中函数式接口的使用

    这是来自的后续问题Java 8 中的 双冒号 运算符 https stackoverflow com questions 20001427 double colon operator in java 8其中 Java 允许您使用以下方式引用
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • Dispatcher-servlet 无法映射到 websocket 请求

    我正在开发一个以Spring为主要框架的Java web应用程序 特别使用Spring core Spring mvc Spring security Spring data Spring websocket 像这样在 Spring 上下文
  • 逃离的正确方法是什么?使用 Oracle 12c MATCH_RECOGNIZE 时 JDBCPreparedStatement 中的字符?

    以下查询在 Oracle 12c 中是正确的 SELECT FROM dual MATCH RECOGNIZE MEASURES a dummy AS dummy PATTERN a DEFINE a AS 1 1 但它不能通过 JDBC
  • 尝试使用等于“是”或“否”的字符串变量重新启动 do-while 循环

    计算行程距离的非常简单的程序 一周前刚刚开始 我有这个循环用于解决真或假问题 但我希望它适用于简单的 是 或 否 我为此分配的字符串是答案 public class Main public static void main String a
  • 无法捕获 Spring Batch 的 ItemWriter 中的异常

    我正在编写一个 Spring Batch 流程来将数据集从一个系统迁移到另一个系统 在这种情况下 这就像使用RowMapper实现在传递给查询之前从查询构建对象ItemWriter The ItemWriter称为save我的 DAO 上的
  • 如何在 Quartz 调度程序中每 25 秒运行一次?

    我正在使用 Java 的 Quartz Scheduling API 你能帮我使用 cron 表达式每 25 秒运行一次吗 这只是一个延迟 它不必总是从第 0 秒开始 例如 序列如下 0 00 0 25 0 50 1 15 1 40 2 0
  • 哪个集合更适合存储多维数组中的数据?

    我有一个multi dimensional array of string 我愿意将其转换为某种集合类型 以便我可以根据自己的意愿添加 删除和插入元素 在数组中 我无法删除特定位置的元素 我需要这样的集合 我可以在其中删除特定位置的数据 也
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • Java:多线程内的 XA 事务传播

    我如何使用事务管理器 例如Bitronix http docs codehaus org display BTM Home JBoss TS http www jboss org jbosstm or Atomikos http www a
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • JAXB - 列表<可序列化>?

    我使用 xjc 制作了一些课程 public class MyType XmlElementRefs XmlElementRef name MyInnerType type JAXBElement class required false
  • 启动Java项目时发生类冲突:ClassMetadataReadingVisitor将接口org.springframework.asm.ClassVisitor作为超类

    我正在使用最新的Spring框架版本 3 2 2 RELEASE 开发一个Java Web项目 但是现在项目启动时遇到了问题 详细错误是 java lang IncompleteClassChangeError 类 org springfr

随机推荐

  • 23_geemap学习笔记

    原文 23 import assets import os import ee import geemap geemap set proxy 10809 Map geemap Map Map out dir os path join os
  • YOLO转VOC格式,解决txt多于jpg问题

    当数据集中标注的txt少于jpg时 转换代码就会报错 一个一个找出多余图片很麻烦 因此对代码进行修改解决这个问题 import os import glob from PIL import Image voc annotations C U
  • layui导入文件时,如何动态传递参数

    需求 点击下图中的下拉框 在导入数据时 动态传递select的值 HTML代码如下 div class layui inline div
  • 服务器和本机共享文件夹,服务器与本地共享目录

    服务器与本地共享目录 内容精选 换一换 云耀云服务器默认设置的时区 是您制作镜像时选择的时区 如需修改 请参见本节内容 将其更改为所需的本地时间或网络中的其他时区 云耀云服务器登录成功后 如果发现云耀云服务器系统时间与本地时间不一致 建议更
  • VTK读取.ply数据并获取顶点,面等信息

    Code by cynthia chen 2021 10 29 include
  • PHP 生成微信小程序二维码

    1 调用方法 调用get qrcode方法 获取二维码图片 base64 img get qrcode id 调用base64 save方法 将图片保存到指定位置 并获取图片新名称 new name base64 save base64 i
  • Android分享文件到微信和QQ功能的实现(兼容android 7.0以上的共享文件)

    Android分享文件到微信和QQ功能的实现 兼容android 7 0以上的共享文件 在android开发过程中 遇到需要分享数据到微信的开发需求时 基本都是集成友盟等第三方开发工具 简单集成SDK并且进行配置后 就可以分享到不同的APP
  • Xshell连接虚拟机详细教程

    Xshell连接虚拟机 1 打开虚拟机终端 输入下面命令 找到ens33对应的IP地址 如图 ifconfig 2 打开Xshell 打开文件 gt 新建 3 填写名称 主机这里填入刚才的IP 点击连接 4 输入登录的用户名 点击确定 5
  • C语言菜单功能作用,[C语言] 实现简单的菜单式互动程序

    1 程序编写目的 编写该程序主要是为了熟悉C语言中的一些常用函数与循环语句的用法 并锻炼自己对于程序设计的逻辑 这对于初学者来说是十分必要的 需要说明的是 本次菜单互动程序为模拟银行存取款的程序 2 实现该程序所需要的技术 2 1常用函数p
  • 也说说LDA(Latent Dirichlet Allocation)——理论篇

    LDA是个generative model 它首先从Dirichlet分布Dir 中抽取每个topic对应的参数 然后语料集D中第j篇文档的产生方式如下 1 选择文档长度 N Poission 2 选择文档参数 Dir 3 按照以下方式选取
  • jar包冲突解决方案

    使用背景 在构建工程中 不可避免的引入多方依赖 从jar包冲突产生结果可大致分为两类 1 同一个jar包出现了多个不同的版本 应用选择了错误的版本导致jvm加载不到需要的类或者加载了错误版本的类 2 不同的jar包出现了类路径一致的类 同样
  • Java实现蓝桥杯分金币

    分金币 圆桌旁坐着n个人 每人有一定数量的金币 金币总数能被n整除 每个人可以给他左右相邻的人一些金币 最终使得每个人的金币数目相等 你的任务是求出被转手的金币数量的最小值 比如 n 4 且4个人的金币数量分别为1 2 5 4时 只需转移4
  • Uni-App 获取用户已装应用列表

    获取用户已装应用列表 plus android importClass java util ArrayList plus android importClass android content pm PackageInfo plus and
  • 【老生谈算法】matlab实现连续时间系统的频域分析与仿真——频域分析

    matlab连续时间系统的频域分析与仿真 1 文档下载 本算法已经整理成文档如下 有需要的朋友可以点击进行下载 序号 文档 点击下载 本项目文档 老生谈算法 matlab连续时间系统的频域分析与仿真 doc 2 算法详解 内 容 摘 要 M
  • Java集合、多线程、反射和Spring框架总结,源码解析

    Java集合 多线程 反射和Spring框架总结 源码解析 一 集合 通过不同的数据结构存储以及操作数据的工具 1 1 Collection 1 1 1 ArrayList Vector 1 1 1 1 底层原理 ArrayList和Vec
  • uniapp踩坑系列之二

    今天在用真机在小程序上预览的时候 发现无法预览 一直报错超过微信最大2m 总共也才3个页面 怎么就那么大 经过小程序包分析工具发现 打包以后的vender js文件达到1 7m 最后发现 在main js中引入了一些无用的第三方库 包括ec
  • WEB页面通过ajax进行图片上传实例(附代码)

    背景 公司需要一个签约页面 支持拍照或选择图片上传 应用场景主要在手机端 页面代码 1 2 3 4 5 6
  • pbr公式推导过程,很好

    渲染基础理论的介绍 1 Tags math computer graphics 基础概念 辐射度学 Radiometry 辐射度学是指测量电磁辐射 包括可见光 的一系列技术 它是和观察者无关的 而近似的光度学 photometric 是观察
  • vlc activex调用

    首先是在html页面调用 第一种方式 下面直接给出的是调用函数 function doGo targetURL port var options new Array vlc input repeat 1 aspect ratio 704 4
  • 代码的认爹之路: 面向对象继承

    面向对象 继承 前言 Hello 各位同学朋友大家好啊 今天给大家分享的技术呢 是面向对象三大特征之一的继承 我们今天主要按照以下几个点 展开继承的讲解 目录 继承的介绍 继承的好处和弊端 继承中成员访问特点 成员变量 继承中成员访问特点