【从零开始学习JAVA | 第十三篇】继承

news2024/11/15 21:35:11

目录

前言: 

引入:

继承:

小拓展:

优点:

 成员方法的继承问题:

总结:


前言: 

 继承是面向对象三大特性之一,它是在封装之后我们讲解的一个重要的性质,继承是类与类之间的关系,子类会继承父类中对子类开放的成员函数以及成员方法。这大大优化了我们在写代码时候的复用性,因此我们要学好继承,这样才可以学好JAVA

引入:

如果此时我们要创建一个学生类,它的成员变量包括姓名,年龄,性别,成员行为包括吃饭,玩游戏,睡觉,学习,要创建一个教师类,它的成员变量包括姓名,年龄,性别,成员行为包括吃饭,玩游戏,睡觉,教学,放到以前我们会这样建立:

但是我们会发现,其实这两个类的行为都是高度相似的,那么我们能否精简一下呢?
这里就用到我们之前说的继承,我们抽象出来一个父类概括这两个类之间的共同点,然后然这两个类继承父类,这样不就降低了代码的复用性。

 其实这就是继承的思想:把类之间的相似点抽象出来,建立一个可以继承的父类,以此来降低代码的复用性。

继承:

Java中,继承是面向对象编程中的重要概念之一,它是指一个类可以继承另一个类的属性和方法,同时可以添加或覆盖父类的功能,从而创建一个新的类。通过继承,子类可以获得父类的全部或部分特性,从而减少代码的重复,简化程序的设计,提高代码的可重用性。

在Java中,一个子类通过  extends  关键字继承一个父类。子类可以访问父类中的公有和受保护的成员变量和方法,但不能访问父类的私有成员变量和方法。子类可以覆盖父类的方法,实现自己特定的行为,或者添加新的方法和属性。

以下是一个简单的Java类继承的示例:

class Animal {
    String name;
    int age;
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Cat extends Animal {
    void meow() {
        System.out.println("Cat is meowing");
    }
}

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.name = "Tom";
        cat.age = 2;
        cat.eat();
        cat.meow();
    }
}

在上述示例中,Cat类继承了Animal类,并添加了一个自己的方法meow。在主程序中,我们创建一个Cat类的对象,并可以访问Animal类的属性和方法,并且可以调用Cat类自己的方法。

小拓展:

JAVA和C++的继承方式非常相似,但是在java中,所有的继承都是公共继承,不存在保护继承和私有继承

在 Java 中,继承可以分为公有继承受保护继承

公有继承(public inheritance)是指子类可以继承父类的公有成员和受保护成员,而不能继承父类的私有成员。

受保护继承(protected inheritance)是指子类可以继承父类的公有成员和受保护成员,但不能直接访问父类的私有成员。(只是不能直接访问而已,在后面我们会介绍方式访问)

实际上,在 Java 中不需要特别声明继承方式,默认使用公有继承。Java 中所有成员变量和方法都有一个访问修饰符,如public、private和protected等,通过使用不同的访问修饰符可以限制子类的访问范围。同时,Java提供了一些关键字,如final和static等,可以在继承时进行限制或定义。

*受保护继承(JAVA)   不是      保护继承(C++)

受保护继承    会把父类的私有成员继承给子类,子类不能直接访问,可以间接访问

保护继承    会把父类的所有成员都继承给子类(私有成员也继承),只不过子类不会提供调                    用的函数,也就相当于没有继承。

如果不相信我们可以调用 vs 2022 管理员后台,进行验证,这里篇幅有限,就不进行验证了。

如何在子类中访问父类中private的变量呢?

如果需要在子类中访问父类的私有变量,可以使用Java中提供的getter和setter方法,通过调用父类的公有方法来实现。

比如,我们在父类中声明了一个私有变量:

public class Parent {
    private int x;
    public Parent(int x) {
        this.x = x;
    }
    private int getX() {
        return x;
    }
}

可以在父类中添加一个公有的getter方法getX(),用于获取私有变量x的值:

public class Parent {
    private int x;
    public Parent(int x) {
        this.x = x;
    }
    private int getX() {
        return x;
    }
    public int getPrivateVariableX() {
        return this.getX();
    }
}

子类可以通过调用父类的公有方法getPrivateVariableX()来获取父类的私有变量x的值:

public class Child extends Parent {
    public Child(int x) {
        super(x);
    }
    public int getPrivateVariableX() {
        return super.getPrivateVariableX();
    }
}

这样就可以在子类中获取并使用父类中的私有变量x了。但是需要注意的是,私有变量在父类中是被限制了访问权限的,而在子类中通过公有方法来访问,可能会造成访问权限的漏洞,因此需要特别注意。

优点:

继承是面向对象程序设计中的一个重要特性,具有以下优点:

1. 代码重用:通过继承,可以将现有的类的代码和功能复用在新的类中,避免了重复编写代码造成资源浪费的问题,提高了代码的复用性。

2. 继承关系体现了程序中的真实的关系:继承关系可以清晰地表示父类与子类之间的关系,从而提高程序的可读性和可维护性。

3. 扩展性好:通过继承可以很方便地扩展一个类并增加新的特性,同时又不会影响到现有的代码和已有的功能。

4. 多态性:通过继承和子类的多态特性,可以使代码更加灵活和可扩展。

5. 代码封装:继承提供了一种封装的方式,父类中的成员可以在子类中被重用,并且对外不可见,保证了代码的安全性和隐私性。

总之,通过继承可以相对简单地实现代码的重用和扩展,使代码更加灵活、可读性更高,并且可以提高代码的可维护性。

介绍到这里,很多小伙伴都会陷入到一个误区既然继承这么便洁,我们以后遇到创建多个类就进行抽象父类,再把父类继承给子类。

这种思想是错误的!这是因为虽然继承很方便,但是我们的父类应该是与子类有一定的相连关系的,这样做是为了提高代码的可读性,例如我们把动物抽象出来,继承给小猫,小狗这样的子类,把手机抽象出来,继承给小米,华为,苹果这样的子类。而不可以随意抽象父类。

JAVA中只支持单继承,不支持多继承,但支持多层继承。

翻译一下:A不可以同时继承B,C(不支持多继承).但是可以让C继承B,A再继承C(多层继承)。

其实这个特性是为了解决C++中的多继承带来的缺陷:如果两个父类的方法名称相似,那么我们的子类如果继承了这两个父类,在调用这个方法的时候,我们到底调用的是哪一个父类中的方法呢?
c++给出的答案是 虚继承

虚继承是指在继承的时候使用关键字  virtual  ,这样的继承方式可以避免派生类继承多个基类中的同名成员(数据和函数)造成的歧义。这是因为虚继承会让派生类只在其继承树中保存一个唯一的基类子对象,从而消除了重复继承的成员。

例如,假设有两个基类A和B,它们都有一个同名函数f(),如果一个类C继承了A和B,那么在调用C::f()时,会发生二义性问题。但如果A和B被虚继承,那么C类只继承一个A子对象和一个B子对象,这样C::f()就不会被重复继承。如果需要在C中调用A或B中的f()函数,可以通过作用域解析符(::)指定调用某个基类的函数,在调用时指定基类A或B即可。

以下是一个示例代码:

class A {
public:
    virtual void f() {
        cout << "A::f()" << endl;
    }
};

class B {
public:
    virtual void f() {
        cout << "B::f()" << endl;
    }
};

class C: public virtual A, public virtual B {
public:
    virtual void f() {
        A::f(); // 调用A的f()函数
        B::f(); // 调用B的f()函数
    }
};

int main() {
    C c;
    c.f(); // 输出 A::f() B::f()
    return 0;
}

而我们的JAVA为了避免这一个繁琐的步骤,就直接禁止了子类进行多父类继承的能力。

 其实每一个类都会直接或间接的继承Object。

在Java中,Object是所有类的根类。Java语言是一门面向对象的语言,所有的类都直接或间接继承了Object类,因此Object类在Java程序中是非常重要和基础的。

Object类定义了一些通用的方法,如:

  • toString()方法:用于返回对象的字符串表示,通常被子类重写。
  • equals()方法:用于比较两个对象是否相等。
  • hashCode()方法:用于返回对象的哈希码,通常被重写。

此外,Object类还定义了一些其他常用的方法,如getClass()方法用于获取对象的类,notify()、notifyAll()和wait()等方法用于线程同步等。

需要注意的是,Object类型是Java中的顶级类型,不是基本类型。在Java中,有八种基本数据类型:byte、short、int、long、float、double、boolean和char。尽管Object类是Java中非常重要的类,但也不要滥用Object类型,尽量使用具体的子类,以便程序具有更好的类型安全性和可读性。

 成员方法的继承问题:

 如果 A 到 D 逐层继承,那么如果我们在A中调用方法C,他真的会逐级父类去找方法D嘛?

实际上是不会这样的,我们有一个虚方法表,各个父类会将自己的方法添加到虚函数表中,供调用的时候快速查询。

虚方法表中的方法必须是:

  • 非private:private关键字修饰的方法只能在本类中访问,无法被子类继承,因此不可能成为虚方法,也不会在虚方法表中存储。

  • 非static:静态方法是属于类而不是对象的,不能被子类继承,因此也不可能成为虚方法,也不会在虚方法表中存储。

  • 非final:final关键字修饰的方法是不能被子类重写的,因此也不可能成为虚方法,也不会在虚方法表中存储。

需要注意的是,在Java中,虚方法表是在运行时动态生成的,基于实际的对象类型,而不是变量的声明类型。这是Java实现多态性的一种高效的方式,可以使程序实现运行时动态绑定,提高代码的可维护性和可扩展性。

总结:

继承是类与类之间的关系,而继承隶属于面向对象的三大特性之一,是一个很重要的性质。因此我们要学好这一个知识点,这样才可以玩转JAVA

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/677256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Kubernetes资源篇】DaemonSet控制器入门实战详解

文章目录 一、DaemonSet控制器理论知识1、DaemonSet控制器是什么&#xff1f;2、DaemonSet控制器工作原理3、DaemonSet典型应用场景4、DaemonSet与Deployment的区别 二、案例&#xff1a;DaemonSet控制器实战演示1、使用DaemonSet部署日志收集组件2、DaemonSet管理Pod滚动更新 …

数据库期末复习大总结 数据库课程学习资料(包含数据库全部章节的经典例题)【我的数据库期末复习】

为刚开始上大学数据库课程 提供学习方向【我的数据库期末复习】 第一章 绪论1.1 数据库系统概述 第二章 关系数据库2.1 关系的基本概念2.2 关系的完整性 关系数据库标准语言SQL3.1.1 SQL创建模式和表3.1.2 SQL修改和删除表3.2.1 SQ单表查询3.2.2 分组聚合和分组过滤3.2.3 多表联…

Matplotlib---散点图

1. 散点图 scatter函数用于绘制散点图。下面是scatter函数的语法格式&#xff1a; scatter(x, y, sNone, cNone, markerNone, cmapNone, normNone, vminNone, vmaxNone, alphaNone, linewidthsNone, edgecolorsNone, **kwargs)参数解释&#xff1a; x&#xff1a;指定散点的…

【二分查找】详细图解

目录 一.什么是二分查找法&#xff1f; 二.算法要求 三.算法思想 图解&#xff08;要找的数k的值为3&#xff09; 参考代码 一.什么是二分查找法&#xff1f; 二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;它是一种效率较高的查找方法。但是&am…

GEE:DYNAMICWORLD/V1数据集介绍

作者:CSDN @ _养乐多_ 本文将介绍GOOGLE/DYNAMICWORLD/V1数据集。 在Dynamic World数据集中,每个波段代表了某个特定类别的土地覆盖概率。这些概率表示了一个像素完全被某种土地覆盖类别所覆盖的可能性,其取值范围从0到1。每个波段的名称和描述指示了对应类别的土地覆盖类…

成为CSDN创作者的第2048天,我收获了什么?

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码…

linux下容器 安装 操作 介绍

介绍&#xff1a; 容器是一种轻量级的虚拟化技术&#xff0c;可以将应用程序及其依赖项打包到一个独立的运行环境中&#xff0c;从而实现快速部署、可移植性和可扩展性。容器可以在不同的操作系统和云平台上运行&#xff0c;使得应用程序的部署和管理变得更加简单和高效。 安…

八大指针笔试题带你overcome指针

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《C语言》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造…

pgsql序列的使用

大家都知道pgsql和mysql不同&#xff0c;mysql字段有有自增属性&#xff0c;pgsql并没有&#xff0c;但是pgsql和oracle一样有序列&#xff0c;很多人刚接触pgsql的时候&#xff0c;并不知道序列是什么&#xff0c;怎么用&#xff0c;下面这篇文章就介绍序列&#xff0c;并且怎…

Flutter系列(十一)实现商城首页和商品详情页

基础工程&#xff1a; Flutter系列&#xff08;四&#xff09;底部导航顶部导航图文列表完整代码_摸金青年v的博客-CSDN博客 一、前言 本文用flutter实现商城首页和商品详情页&#xff0c;效果如下图&#xff1a; 二、使用的组件 MasonryGridView.count 瀑布流插件&#xff…

几何引擎 约束求解器 3D仿真物理引擎 图形引擎

几何引擎 & 约束求解器 & 3D仿真物理引擎 & 图形引擎 1 介绍技术图谱建模主流CAD/CAM/CAE/AEC所用引擎 2 几何建模引擎2.1 介绍2.2 各家实现 3 图形引擎4 几何约束求解器4.1 介绍4.2 各家实现D-Cubed DCM&#xff08;西门子&#xff09;CGM(达索&#xff09;LGS&am…

OpenGL模型控制(旋转、平移)

1.效果图 2.平移 首先做一个鼠标双击事件&#xff0c;表示平移模型对象&#xff0c;当然&#xff0c;我们需要遍历当前哪个模型对象被选中&#xff0c;才能进行该对象的平移操作。 void AXBOpemglWidget::mouseDoubleClickEvent(QMouseEvent *event) {Q_UNUSED(event);if(m_m…

团体程序设计天梯赛-练习集L1篇⑥

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

命令行编译C程序

目录 设置MSVC环境变量 C文件编译流程 编译 链接 学习起步之初&#xff0c;先用最基础的命令行工具进行学习 设置MSVC环境变量 这个是在VS2019下进行配置的&#xff0c;位置和你安装IDE的位置有关 MSVC D:\VS2019\IDE\VC\Tools\MSVC\14.29.30133WK10_INCLUDE C:\Program …

Android App安装弹窗显示流程

一、APP的安装 1、常见安装方式 系统应用和预制应用安装――开机时完成&#xff0c;没有安装界面&#xff0c;在PKMS的构造函数中完成安装 网络下载或第三方应用安装――调用PackageManager.installPackages()&#xff0c;有安装界面。 ADB工具安装――没有安装界面&#xf…

社交登陆成功回调

1. 点击跳转至第三方授权 2. 这是使用gitee作为第三方授权进行验证 3. 授权成功则跳转至 redirect_url 4. 社交登陆回调逻辑 一、根据第三方授权提供的方式获取token &#xff08;1&#xff09;发送请求获取code码&#xff08;每次发送请求&#xff0c;code码会改变&#xff…

构建安全架构的 Azure 云:深入了解零信任体系结构

文章目录 前言一、零信任安全模型的概念以及背景介绍二、传统安全模型&#xff08;边界模型&#xff09;三、零信任模型&#xff08;现阶段主流云厂商策略&#xff09;四、Azure 中的零信任体系结构&#xff08;本文重点&#xff09;4.1 基础知识点&#xff08;必须了解&#x…

File 类,InputStream, OutputStream 的用法

目录 一.File类 关于名字和路径的操作 关于创建和销毁的操作 创建文件夹(多级目录) InputStream 第一种:字节流读取 第二种: 字符流读取(Reader) OutputStream 第一种:字节流写入 第二种方式:字符流输入 一.File类 File翻译过来"文件" 那么File类的操作实际…

【初识 Docker | 中级篇】 Docker 安装 Redis

文章目录 前言一、安装 docker1、安装docker2、安装docker-compose 二、redis 单机安装1.创建配置文件1.1.创建目录1.2.创建redis.conf1.3.创建docker-compose.yml 2.启动redis容器 总结 前言 可以按照以下步骤在 Docker 中安装 Redis docker pull redis 拉取Redis镜像 docker…

CSS3-定位

网页常见布局方式 1 标准流 1 块级元素独占一行 → 垂直布局 2 行内元素/行内块元素一行显示多个 → 水平布局 2 浮动 可以让原本垂直布局的 块级元素变成水平布局 3 定位 1 可以让元素自由的摆放在网…