java基础(5)继承与多态

news2024/12/28 18:30:27

4480802ac4a84437adcb9e39c4427f32.jpeg


目录

​编辑

1.前言

2.正文

2.1继承

2.1.1继承概念

2.1.2继承语法

2.1.3子类访问父类

2.1.4super关键字

2.2多态

2.2.1多态概念

2.2.2多态条件

2.2.3重写

2.2.4向上转型与向下转型

2.2.5为什么要使用多态

3.小结


1.前言

哈喽大家好啊,今天继续来为大家分享java基础语法的学习,今天分享的是java中的继承与多态,也是Java基础学习当中非常重要的一部分,话不多说让我们开始吧。

2.正文

2.1继承

2.1.1继承概念

先让我们来引入一下继承,当我们在java编写程序的时候,会创建许多个类,如果每个类都单独创建的话,会使代码看起来非常的冗长,于是对于有相同特点的类,我们对其进行共性的抽取,便有了继承的概念。

b6ab0b961d164eedbc14ba240f0fe0eb.png

继承是一种面向对象编程(OOP)的核心概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。使用继承可以创建一个层次结构,其中子类继承父类的属性和方法,并且可以添加或覆盖它们。 

2.1.2继承语法

那么继承的语法是如何实现的呢。这里我们就需要运用extends关键字,具体例子参照上面那个图,让我们附上代码。

person父类:

public class person {
    String name;
    int age;

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

    public void func(){
        System.out.println("目前在学校");
    }
}

student子类:

public class student extends person {
    int id;

    public student(String name, int age, int id) {
        super(name, age);
        this.id = id;
    }

    public void havaClass() {
        System.out.println("在听课");
    }
}

teacher子类:

public class teacher extends person{
    String subject;

    public teacher(String name, int age, String subject) {
        super(name, age);
        this.subject = subject;
    }

    public void makeClass() {
        System.out.println("在上课");
    }
}

测试类: 

public class test {
    public static void main(String[] args) {
        student s1 = new student("张三",16,001);
        teacher t1 = new teacher("李四",42,"语文");

        s1.havaClass();
        s1.func();

        t1.func();
        t1.makeClass();
    }
}

 运行结果如图:

12ac4fcd05ca4f5ea63b7bb349fc0089.png

2.1.3子类访问父类

让我们先来观察下面这段代码:

public class test {
    static public class A{
        int a = 1;
    }
    static public class B extends A{
        int a = 2;
        int b = 3;
    }
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.a);
        System.out.println(b.b);
    }
}

我们可以看到,在类A与类B中均对a整型进行了定义,那么打印的结果会是怎样呢?

353b88cd56704936a64c47f0a531d678.png

我们可以看到,打印的是子类定义的a与b而非父类中的定义。那如果我们将类B中的int a删除呢?

7f165ca5675a41c09c6743d3a860b8c2.png

这里打印出来的就是父类中定义的a和子类中定义的b,如果我们再将父类A中的int a删除呢,很显然编译器直接报错,由此我们可以得出:

  • 如果访问的成员变量子类中有,优先访问自己的成员变量。
  • 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。

同理,访问成员方法也是这个道理:

  • 如果一个方法子类中定义就优先子类,子类中没有就去父类里面,父类也没有编译器就报错。
  • 如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错

2.1.4super关键字

学到这里,我们已经基本明白了如何通过子类访问父类,但如果我们遇到,子类与父类存在变量名相同的情况,此时想访问父类里的同名变量时如何更好的去访问呢?这里我们就引入了super关键字。

super关键字可以访问父类的成员变量,构造方法以及成员方法,下面这段代码将都展示出来:

成员变量:

public class A{
        int a = 1;
    }
public class B extends A{
        public void func() {
            System.out.println(super.a);
        }
}

构造方法:

public class A{
        int num;

        public A(int num) {
            this.num = num;
        }
    }
public class B extends A{
        String str ;

        public B(int num, String str) {
            super(num);
            this.str = str;
        }
}

成员方法:

public class test {
    public static class A {
        public void func() {
            System.out.println(1);
        }
    }

    public static class B extends A {
        public void func() {
            super.func();
        }
    }

    public static void main(String[] args) {
        B b = new B();
        b.func();  
    }
}

 e741410d343f42269791c3583b037076.png

另外有一些需要注意的点:

  • 用户没有写构造方法时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句。
  • 当子类继承父类需要先初始化继承过来的父类的成员,此时需要通过super来完成。如果没有通过super调用父类的构造方法,编译器会报错。
  • 只能在类的非静态方法中使用,用来访问非静态成员方法和字段。
  • 在java中不支持多继承,若在写代码过程中想要限制多层继承,可以使用final关键字。

 2.1.5final关键字

final关键字可以用于类,变量,方法上,接下来附上代码方便理解

当修饰类时,该类则不能被继承:

public class test {
    public static final class A {
        public void func() {
            System.out.println(1);
        }
    }

    public static class B extends A {
        @Override
        public void func() {
            super.func();  // 调用父类的func方法
            System.out.println(2);
        }
    }

    public static void main(String[] args) {
        B b = new B();
        b.func();  // 调用b的func方法
    }
}

5674e63236fb4411845fee4c2db9bfd7.png

当修饰方法时,该方法仅能被调用与继承,而并不能被重写:

public class test {
    public static class A {
        public final void func() {
            System.out.println(1);
        }
    }

    public static class B extends A {
        @Override
        public void func() {
            super.func();  // 调用父类的func方法
            System.out.println(2);
        }
    }

    public static void main(String[] args) {
        B b = new B();
        b.func();  // 调用b的func方法
    }
}

aa5187a42d28418e8f616ee55a36c23f.png

当修饰变量时,该变量则不能被修改:

public static void main(String[] args) {
    final int a = 10;
    a = 20;
}

 c52166ed136c4166b2cd296ea619bf20.png

2.2多态

2.2.1多态概念

让我们先引入多态这个概念,当我们在书写代码时创建多个类时,如学生类和老师类,创建俩个类的方法时,有的方法可能存在类似,但处理后的结果却不同,如老师拿到试题是改作业,学生拿到试题是写试题。鉴于这种情况,我们便引入了多态。

多态(Polymorphism)是面向对象编程(OOP)的一个核心概念。它允许同一个类型的对象在不同的情况下表现出不同的行为。这种特性使得Java程序具有更好的可扩展性、可维护性和可重用性。

2.2.2多态条件

达成多态的条件有以下几个:

  • 必须在继承体系下
  • 子类必须对父类中方法进行重写(何为重写下文讲解)
  • 必须通过父类来引用重写的方法

附上代码:

public class test {
    public static class A {
        public void func() {
            System.out.println(1);
        }
    }

    public static class B extends A {
        @Override//标记重写
        public void func(){
            System.out.println(2);
        }
    }

    public static class C extends A {
        @Override//标记重写
        public void func(){
            System.out.println(3);
        }
    }

    public static void main(String[] args) {
        B b = new B();
        C c = new C();
        b.func();
        c.func();
    }
}

 我们可以看到实例化b与实例化c都调用了func函数,那么究竟是父类还是子类的func呢?

20ef3bd365b94604b819a8dccd8b3eca.png

根据上文的讲解我们也应该很容易得出,分别调用的是子类重写后的方法。

2.2.3重写

我们上文用了这么多重写,那么到底何为重写呢,下文我们详细盘一盘:

重写(Override)是面向对象编程中的一个重要概念,子类可以重新定义父类中已经定义过的方法,这样当通过子类的实例来调用该方法时,就会执行子类中的实现版本,而不是父类中的版本。


重写的具体规则如下:

  1. 方法签名必须相同:重写的方法必须与父类中被重写的方法具有相同的名称、返回类型和参数列表。

  2. 访问修饰符:子类重写的方法的访问修饰符不能比父类中被重写的方法的访问修饰符更严格。例如,如果父类中的方法是public,那么子类中的重写方法也必须是public。但是,子类可以使用更宽松的访问修饰符,如protected

  3. 不能重写final方法:如果父类中的方法是final的,那么子类不能重写该方法。

  4. 不能重写static方法:静态方法属于类本身,而不是类的实例。因此,子类不能重写父类中的静态方法。

2.2.4向上转型与向下转型

向上转型与向下转型有点类似于数据类型中int与long之间的强转,接下来就让我们来分别介绍何为向上转型,何为向下转型。

向上转型,指的是将一个子类对象的引用赋值给一个父类类型的变量,而向下转型(Downcasting)是指将父类引用类型转换为子类引用类型的过程。

代码如下:

public class test {
    public static class A {
        int a = 1;
    }

    public static class B extends A {
        int b = 2;
    }

    public static void main(String[] args) {
        A a = new B();//向上转型
        if (a instanceof B) {
            B b = (B) a; // 强制类型转换//向下转型
        }
    }
}

其中在进行向下转型之前,通常需要使用instanceof关键字来判断父类引用是否指向了一个子类对象,这是为了确保类型转换的安全性。

2.2.5为什么要使用多态

到此为止我们已经大概讲解完了堕胎的概念以及重写的使用,那我们这样编写代码有什么优缺点呢?

优点有以下主要几点:


提高代码的灵活性和可扩展性

  • 多态允许在运行时动态地决定调用哪个方法,这使得代码更加灵活,易于扩展。
  • 当需要添加新的子类时,只需确保新子类实现了父类或接口中的方法,而无需修改现有代码。

简化代码

  • 通过多态,可以使用父类引用来操作子类对象,从而简化代码结构,减少重复代码。
  • 多态使得代码更加通用,因为父类引用可以指向任何子类对象。

而缺点也显而易见:


性能开销

  • 多态的实现通常依赖于动态绑定,即在运行时决定调用哪个方法。
  • 这可能会使代码的运行效率降低。

复杂性增加

  • 多态使得代码结构更加复杂,因为需要理解父类、子类以及它们之间的关系。

调试难度增加

  • 由于多态允许在运行时动态地决定调用哪个方法,因此调试时可能难以确定哪个方法被实际调用。
  • 会增加调试的难度和时间成本。

3.小结

今天关于继承与多态的讲解到这里就结束了,喜欢的小伙伴不要忘了点点关注点点收藏支持一下哦,你的支持就是对我最大的鼓励。

 

 

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

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

相关文章

汽车开发流程管理工具赋能安全与质量

随着数字化、人工智能、自动化系统及物联网技术的迅速发展,工程驱动型企业正面临重大转型挑战,亟需加速并深化其变革步伐。众多企业正试图通过采用基于模型的系统工程(MBSE)、产品线工程(PLE)、ASPICE、安全、网络安全、软件定义汽车、敏捷和精益开发实践…

微信小程序上传组件封装uploadHelper2.0使用整理

一、uploadHelper2.0使用步骤说明 uploadHelper.js ---上传代码封装库 cos-wx-sdk-v5.min.js---腾讯云,对象存储封装库 第一步,下载组件代码,放置到自己的小程序项目中 第二步、 创建上传对象,执行选择图片/视频 var _this th…

【java Web如何开发?】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

讯飞与腾讯云:Android 实时语音识别服务对比选择

在 移动端 接入实时语音识别方面,讯飞和腾讯云都是优秀的选择,但各有其特点和优势。以下是对两者的详细比较: 一、讯飞语音识别 1.1 讯飞实时语音识别介绍 1.1.1 功能特点 1.支持多种语言识别,满足不同语种用户的需求。(普通话/…

Kafka之消费者组与消费者

消费者(Consumer)在Kafka的体系结构中是用来负责订阅Kafka中的主题(Topic),并从订阅的主题中拉取消息后进行处理。 与其他消息中间件不同,Kafka引入一个逻辑概念——消费组(Consumer Group&…

使用excel.js(layui-excel)进行layui多级表头导出,根据单元格内容设置背景颜色,并将导出函数添加到toolbar

本段是菜狗子的碎碎念,解决办法请直接从第二段开始看。layui多级表头的导出,弄了两天才搞定,中途一度想放弃,还好坚持下来了。一开始用的是layui的toolbar里自带的那个导出,但是多级表头没有正常导出,单元格…

FPGA学习(6)-基础语法参数化设计阻塞与非阻塞

目录 1.两种参数化不改变源文件,只改仿真文件的值 2.参数化设计实现模块的重用 2.1不用参数化方法 2.1.1源文件 2.1.2仿真文件 2.1.3仿真波形及实验 2.2 用参数方法 2.2.1调用之前写的led灯闪烁模块,在本源函数中,例化4次调用之前的模…

【pyspark学习从入门到精通7】DataFrames_2

目录 创建 DataFrames 生成我们自己的 JSON 数据 创建 DataFrame 创建临时表 简单的 DataFrame 查询 DataFrame API 查询 SQL 查询 创建 DataFrames 通常,您会通过使用 SparkSession(或在 PySpark shell 中调用 spark)导入数据来创建 …

SpinalHDL之错误集(一)

本文作为SpinalHDL学习笔记第七十六篇,作为错误集使用,类似高中生的错题集,记录使用SpinalHDL过程中遇到的问题,小到语法错误、版本兼容问题,大到SpinalHDL库函数错误等等,持续更新。 SpinalHDL学习笔记总…

记录 ruoyi-vue-plus在linux 部署遇到的问题

整理 linux 文件不要放在 /, 根目录下,要放在 home 文件夹下。docker 启动mysql 容器,映射的 my.cnf 文件不能设置太高权限,权限太高有安全问题,无法读取。 linux 使用注意事项 docker 文件夹 部署在home文件夹下 总结学习到的…

Asp.Net Core 发布 IIS、docker、Azure、文件夹、AAS、ASF、AWM等

发布 微软资料 微软资料 在 IIS 工作进程 (w3wp.exe) 内托管 ASP.NET Core 应用,称为进程内托管模型。 将 Web 请求转发到运行 Kestrel 服务器的后端 ASP.NET Core 应用,称为进程外托管模型。 发布到IIS 》》》Asp.net 之前 》》》 Asp.net Core …

JavaScript 网页设计案例:使用 Canvas 实现趣味打气球小游戏

JavaScript 网页设计案例:使用 Canvas 实现趣味打气球小游戏 在网页设计中,交互性和趣味性是吸引用户的重要因素。借助 JavaScript 和 HTML5 的 canvas 元素,我们可以轻松实现各种动画效果,今天将带你打造一个有趣的 打气球小游戏…

Vxe vue vxe-table 分享实现打印表格以及同时打印两张表

Vxe vue vxe-table 分享实现打印表格以及同时打印两张表 vxe-table 默认情况下支持单表打印。 在有些情况下,页面上同时有几张表,这时需要一次性打印出来。可以利用 Vxe 自带的分页打印功能,实现多张表同时打印。 效果 点击打印后自动调起预…

Redis --- 第四讲 --- 常用数据结构 --- set、zset

一、set类型的基本介绍 谈到一个术语,这个术语很可能有多种含义。Set一个含义是集合,一个含义是设置。 集合就是把一些有关联数据放到一起。 1、集合中的元素是无序的! 2、集合中的元素是不能重复的。 和list类似,集合中的每…

数据治理为何如此简单?

欢迎来文末免费获取数据治理相关PPT和文档 引言 随着大数据技术的迅速发展,企业积累的数据量呈现爆炸式增长。有效的数据管理已经成为企业提高决策效率、增强竞争优势的重要手段。在这样的背景下,数据治理逐渐成为企业数据管理中不可或缺的一环。它不仅…

15分钟学Go 第1天:Go语言简介与特点

Go语言简介与特点 1. Go语言概述 Go语言(又称Golang)是由谷歌于2007年开发并在2009年正式发布的一种开源编程语言。它旨在简单、高效地进行软件开发,尤其适合于网络编程和分布式系统。 1.1 发展背景 多核处理器:随着计算机硬件…

MFC扩展库BCGControlBar Pro v35.1新版亮点:改进网格控件性能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.1已全新发布了,这个版本改进网格控件的性能、增强工具栏编辑器功能等。 …

hadoop集群搭建-克隆虚拟机,安装jdk,hadoop

2.2 hadoop运行环境的搭建 2.2.1 环境准备 1)安装模板虚拟机,IP地址 192.168.10.100,主机名hadoop100,内存41GB,硬盘50GB 2)虚拟机配置 首先测试虚拟机是否可以正常上网,测试方法ping www.b…

HarmonyOS Next模拟器异常问题及解决方法

1、问题1:Failed to get the device apiVersion. 解决方法:关闭模拟器清除用户数据重启

centos7.9调整磁盘分区大小

在安装centos7.9时我们一般采用默认分区设置,使用LVM来管理磁盘空间,根分区只有50GB,其余的所有可用空间都分配在/home分区下。可是centos7中大多数的应用软件都是安装在根分区的,在使用过程中经常会出现明明系统还有很大的磁盘空…