Java入门到精通——第十五单元 多态(没有十四哦)_多态技能目标-程序员宅基地

技术标签: java  

昨日知识点回顾

  1. 接口的概念?
  2. 接口的定义是什么?
  3. 接口如何实现?

本单元知识点概述

在这里插入图片描述


本单元教学目标

(Ⅰ)重点知识目标

1.多态的概念
2.多态的体现
3.多态的好处
4.接口多态的综合案例

(Ⅱ)能力目标

1.掌握多态的概念
2.掌握多态的好处
3.掌握接口多态的综合案例


本单元知识详讲

15.1 多态

15.1.1 概念引入★★★

多态是继封装、继承之后,面向对象的第三大特性。生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

水:H2O

15.1.2 多态的定义★★★

多态: 是指同一行为,具有多个不同表现形式。

前提【重点】:

  1. 继承或者实现【二选一】
  2. 方法的重写【意义体现:不重写,无意义】
  3. 父类引用指向子类对象【格式体现】

15.1.3 多态体的体现★★★★

多态体现的格式:

父类类型 变量名 = new 子类对象;
变量名.方法名();

父类类型:指子类对象继承的父类类型,或者实现的父接口类型

代码如下:

Fu f = new Zi();
f.method(); 

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。
代码如下:
定义父类:

public abstract class Animal {
    
	public abstract void eat();
}

定义子类:

class Cat extends Animal {
    
    public void eat() {
    
   		System.out.println("吃鱼");
    }
} 
class Dog extends Animal {
    
    public void eat() {
    
   	 	System.out.println("吃骨头");
    }
}

定义测试类:

public class Test {
    
    public static void main(String[] args) {
    
        // 多态形式,创建对象
        Animal a1 = new Cat();
        // 调用的是 Cat 的 eat
        a1.eat();
        // 多态形式,创建对象
        Animal a2 = new Dog();
        // 调用的是 Dog 的 eat
        a2.eat();
	}
}

15.1.4 多态的好处★★★★★

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展
性与便利。代码如下:

定义父类:

public abstract class Animal {
    
	public abstract void eat();
}

定义子类:

class Cat extends Animal {
    
    public void eat() {
    
    	System.out.println("吃鱼");
    }
}
class Dog extends Animal {
    
    public void eat() {
    
    	System.out.println("吃骨头");
    }
}

定义测试类:

public class Test {
    
public static void main(String[] args) {
    
    // 多态形式,创建对象
    Cat c = new Cat();
    Dog d = new Dog();
    // 调用showCatEat
    showCatEat(c);
    // 调用showDogEat
    showDogEat(d);
    /*
    以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
    而执行效果一致
    */
    showAnimalEat(c);
    showAnimalEat(d);
    } 
    public static void showCatEat (Cat c){
    
    	c.eat();
    } 
    public static void showDogEat (Dog d){
    
    	d.eat();
    } 
    public static void showAnimalEat (Animal a){
    
    	a.eat();
    }
}

由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当然可以把Cat对象和Dog对象,传递给方法。

当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上两方法。

不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用showAnimalEat都可以完成。

所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。

15.1.5 向上转型★★★★★

  • 向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。

当父类引用指向一个子类对象时,便是向上转型。

使用格式:

父类类型 变量名 = new 子类类型();
代码举例:Animal a = new Cat();

15.1.6 向下转型★★★★★

  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。

一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:

子类类型 变量名 = (子类类型) 父类变量名;
代码举例:Cat c =(Cat) a; 

15.1.7 转型的使用场景★★★★★

为什么要转型

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

转型演示,代码如下:

定义类:

abstract class Animal {
    
	abstract void eat();
} 
class Cat extends Animal {
    
    public void eat() {
    
        System.out.println("吃鱼");
	} 
	public void catchMouse() {
    
		System.out.println("抓老鼠");
	}
} 
class Dog extends Animal {
    
    public void eat() {
    
    	System.out.println("吃骨头");
	} 
    public void watchHouse() {
    
    	System.out.println("看家");
    }
}

定义测试类:

public class Test {
    
    public static void main(String[] args) {
    
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        Cat c = (Cat)a;
        c.catchMouse(); // 调用的是 Cat 的 catchMouse
    }
}

15.1.8 转型的异常★★★

转型的过程中,一不小心就会遇到这样的问题,请看如下代码:

public class Test {
    
    public static void main(String[] args) {
    
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        Dog d = (Dog)a;
        d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】
    }
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false

所以,转换前,我们最好先做一个判断,代码如下:

public class Test {
    
    public static void main(String[] args) {
    
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        if (a instanceof Cat){
    
            Cat c = (Cat)a;
            c.catchMouse(); // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
    
            Dog d = (Dog)a;
            d.watchHouse(); // 调用的是 Dog 的 watchHouse
        }
    }
}

15.2 接口多态的综合案例

笔记本电脑(laptop)通常具备使用USB设备的功能。在生产时,笔记本都预留了可以插入USB设备的USB接口,但具体是什么USB设备,笔记本厂商并不关心,只要符合USB规格的设备都可以。

定义USB接口,具备最基本的开启功能和关闭功能。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,实现USB接口,否则鼠标和键盘的生产出来也无法使用。

15.2.1 案例分析★★★

进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘

  • USB接口,包含开启功能、关闭功能
  • 笔记本类,包含运行功能、关机功能、使用USB设备功能
  • 鼠标类,要实现USB接口,并具备点击的方法
  • 键盘类,要实现USB接口,具备敲击的方法

15.2.2 案例实现★★★

定义USB接口:

interface USB {
    
    void open();// 开启功能
    void close();// 关闭功能
}

定义鼠标类:

class Mouse implements USB {
    
    public void open() {
    
    	System.out.println("鼠标开启,红灯闪一闪");
    } 
    public void close() {
    
        System.out.println("鼠标关闭,红灯熄灭");
    } 
    public void click(){
    
        System.out.println("鼠标单击");
    }
} 

定义键盘类:

class KeyBoard implements USB {
    
    public void open() {
    
    	System.out.println("键盘开启,绿灯闪一闪");
    } 
    public void close() {
    
    	System.out.println("键盘关闭,绿灯熄灭");
    } 
    public void type(){
    
        System.out.println("键盘打字");
    }
}

定义笔记本类:

class Laptop {
    
    // 笔记本开启运行功能
    public void run() {
    
    	System.out.println("笔记本运行");
    } 
    // 笔记本使用usb设备,这时当笔记本对象调用这个功能时,必须给其传递一个符合USB规则的USB设备
    public void useUSB(USB usb) {
    
        // 判断是否有USB设备
        if (usb != null) {
    
            usb.open();
            // 类型转换,调用特有方法
            if(usb instanceof Mouse){
    
                Mouse m = (Mouse)usb;
                m.click();
            }else if (usb instanceof KeyBoard){
    
                KeyBoard kb = (KeyBoard)usb;
                kb.type();
            } 
            usb.close();
           }
    } 
    public void shutDown() {
    
        System.out.println("笔记本关闭");
    }
}

测试类,代码如下:

public class Test {
    
    public static void main(String[] args) {
    
        // 创建笔记本实体对象
        Laptop lt = new Laptop();
        // 笔记本开启
        lt.run();
        // 创建鼠标实体对象
        Usb u = new Mouse();
        // 笔记本使用鼠标
        lt.useUSB(u);
        // 创建键盘实体对象
        KeyBoard kb = new KeyBoard();
        // 笔记本使用键盘
        lt.useUSB(kb);
        // 笔记本关闭
        lt.shutDown();
    }
}

本单元知识总结

1.多态的概念
2.多态的体现
3.多态的好处
4.接口多态的综合案例

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_50009850/article/details/123655836

智能推荐

基于灰狼优化算法优化XGBOOST实现故障数据分类附matlab代码GWO-XGBOOST-程序员宅基地

文章浏览阅读35次。故障数据分类一直是工程领域中一个重要的课题,尤其是在大型设备和系统中。通过对故障数据进行分类,我们可以更好地理解设备的运行状况,及时发现问题,并采取相应的措施进行维修和保养。在过去的研究中,XGBOOST算法在故障数据分类中取得了一定的成果,但是在实际应用中仍然存在一些问题,比如算法的收敛速度和分类准确度等方面还有待提高。近年来,灰狼优化算法作为一种新兴的优化算法,受到了越来越多研究者的关注。该算法模拟了灰狼群体的社会行为,具有较强的全局寻优能力和快速收敛速度,逐渐被应用到了各个领域。

内网渗透--压缩数据_渗透 rar.exe 命令行压缩文件-程序员宅基地

文章浏览阅读635次。内网渗透--压缩数据使用WinRAR 工具进行解压缩1、以RAR 格式压缩/解压2、分卷压缩/解压使用7-Zip 工具进行解压缩1、普通压缩解压方式2、分卷压缩/解压方式在渗透测试中,数据的下载也是重要的一部分,通常我们使用winrar、7-zip 进行压缩数据而后进行下载。使用WinRAR 工具进行解压缩 目标机器上安装了 WinRAR,可以直接使用;如果没有安装,可以在本地下载并安装,然后把 WinRAR安装目录里的 rar.exe文件提取出来,上传到目标机器中(安装 WinRAR的_渗透 rar.exe 命令行压缩文件

高性能软件负载OpenResty介绍和安装_openresty安装-程序员宅基地

文章浏览阅读1.2k次。目录1 OpenResty介绍1.1 Nginx 的流程定义1.1.1 流程详解1.1.2 OpenResty处理流程2 Openresty安装2.1 yum安装2.1.1 添加OpenResty仓库2.1.2 安装OpenResty2.2 源代码编译安装2.2.1 安装编译环境2.2.2下载最新版源码2.2.3下载缓存插件2.2.4 编译OpenResty2.2.5 安装OpenResty2.2.6 环境设置2.2.7 查看环境2.8 环境配置2.8.1 配置文件修改_openresty安装

云原生主题学习月|成为社区领学员,解锁专属奖励及超多数量社区学员奖品!_云原生活动卖点-程序员宅基地

文章浏览阅读331次。每门课程时长从十分钟到几小时不等,由亚马逊云科技专家打造,其中包括最受欢迎的《亚马逊云科技云从业者必修知识》,涵盖了亚马逊云科技的云概念、核心服务、安全性、架构、定价和支持系统等内容,能够帮助学习者构建基础的云知识体系。您将了解亚马逊云科技云概念、亚马逊云科技服务、安全性、架构、定价和支持,以积累亚马逊云科技云知识。研讨会将探讨考试的主题领域,介绍它们与亚马逊云科技上的架构设计的关系,并把它们对应到特定的领域,以便将来自学。本活动在社区进行,领学员可以是个人社区创建者,或是高校社区的管理员。_云原生活动卖点

正点原子bootloader代码(STM32F103ZET6)粗略解读_正点原子f103 bootloader模式-程序员宅基地

文章浏览阅读943次,点赞19次,收藏18次。关于正点原子IAP程序解读_正点原子f103 bootloader模式

多目标麻雀搜索优化算法及其MATLAB实现_多目标麻雀优化-程序员宅基地

文章浏览阅读186次。麻雀搜索优化算法(Sparrow Search Optimization,简称SSO)是一种基于麻雀行为的启发式优化算法,用于解决多目标优化问题。该算法模拟了麻雀在觅食和寻找栖息地过程中的行为,通过群体合作和信息共享来寻找最优解。本文将介绍多目标麻雀搜索优化算法的原理,并提供MATLAB实现的源代码。本文介绍了多目标麻雀搜索优化算法的原理,并提供了MATLAB实现的源代码。通过模拟麻雀的觅食和寻找栖息地行为,该算法在解决多目标优化问题上具有一定的效果。使用时,可以根据具体的多目标优化问题,实现。_多目标麻雀优化

随便推点

tp6连接oracle数据库save和insert语句执行成功但是报ORA-00936: 缺失表达式错误_oracle insert 缺失表达式-程序员宅基地

文章浏览阅读2.7k次。错误现象:使用thinkphp6连接oracle数据库时使用save方法永远跳转到update使用insert方法执行语句成功,但是总是报ORA-00936错误错误截图:SQLSTATE[HY000]: General error: 936 OCIStmtExecute: ORA-00936: 缺失表达式(ext\pdo_oci\oci_statement.c:157) /** * 获取最近插入的ID * @access public * @param..._oracle insert 缺失表达式

python 图像处理就业_python+cv环境下的图像处理-程序员宅基地

文章浏览阅读126次。一、直方图1.1原理直方图是数值数据分布的精确图形表示。 这是一个连续变量的概率分布的估计,是一种条形图。为了构建直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 这些值通常被指定为连续的,不重叠的变量间隔。 间隔必须相邻,并且通常是(但不是必须的)相等的大小。在画图像轮廓前需要将原图像转换为灰度图像,因为轮廓需要获取每个坐标[x,y]位置的像素值。1...._im = array(image.open(img_path).convert('l')) typeerror: array() argument 1

java http 请求网页保存导入写入 本地 文件_java http接口获取数据,结果写入文件-程序员宅基地

文章浏览阅读828次。目录依赖调用获取网页写入本地import依赖<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5.2</version..._java http接口获取数据,结果写入文件

lists这个类无法使用maven打包_lists maven-程序员宅基地

文章浏览阅读1.6k次。org.assertj assertj-core_lists maven

关于微信小程序打包文件vendor.js超过500k的压缩方案_发行时压缩vendor文件-程序员宅基地

文章浏览阅读5.4k次。关于微信小程序打包文件vendor.js超过500k的压缩方案因为是开发环境,所以没进行UglifyJs压缩,所以解决的方法来了,引入UglifyJs插件修改build目录下 的webpack.dev.conf.js配置文件,前面添加插件的引入,var UglifyJsPlugin = require('uglifyjs-webpack-plugin') // 在插件列表加上一句话,就可将..._发行时压缩vendor文件

C语言--指针详解(下)--字符指针、数组指针、指针数组、函数指针、函数指针数组(转移表)-程序员宅基地

文章浏览阅读1k次,点赞33次,收藏30次。字符指针、数组指针、指针数组、函数指针、函数指针数组涵盖了在指针学习中有关指针的绝大多数的情况,熟练掌握它们,将对学习指针有巨大的帮助。同时,指针部分是C语言学习中重要的部分之一,熟练掌握指针对于C语言学习来说很重要。