Java学习笔记007——接口的应用

1、接口的转换(向下)

子类对向和父类对象可以进行类型转化。接口也一样可以。

package com.test;// 接口Animal
public interface Animal {void bark(); //等价于public abstract void bark();void move(); //等价于public abstract void move();
}package com.test;// 通过接口Animal实现的Dog类
public class Dog implements Animal{public void bark() {System.out.println("狗在叫.");}public void move() {System.out.println("狗在奔跑。");}
}// 通过接口Animal实现的Cat类
public class Cat implements Animal{public void bark() {System.out.println("猫在喵。");}public void move() {System.out.println("猫在跳。");}
}// 通过实现两个接口,包括Animal接口的类Bird
public class Bird implements Animal,Flyable{public void bark() {System.out.println("鸟在唱歌。");}public void move() {System.out.println("鸟在蹦蹦跳跳。");}public void fly() {System.out.println("鸟在飞翔。");}
}//
public class Zoo {public static void main(String[] args) {Animal[] animals = {new Dog(),new Cat(),new Bird()};for (Animal an : animals) {an.bark();an.move();}((Flyable)animals[2]).fly();}
}

上面代码有两个接口Animal和Flyable,类Dog、Cat分别实现了Animal接口,类Bird同时实现了Animal和Flyable两个接口。

因为类Dog、Cat、Bird都实现了接口Animal,上面代码中定义的Animal类型的数组animals中的成员可以包含Dog、Cat、Bird类的实例对象。即下面一行代码是被Java允许的:

Animal[] animals = {new Dog(),new Cat(),new Bird()};

这样,数组中animals的元素(Animal类型变量)可以执行Animal接口中定义的,并在Dog、Cat、Bird类中实现的方法(bark()和move())。

animals[2]是Bird类的实例对象,但是它被声明成父接口Animal类型,要使用Bird类中实现的Flyable接口中的fly()方法,需要“向下转换”,即使用一对括号(子类/子接口)把animals[2]转换为Flyable接口类型,然后就可以调用Flyable接口中定义的,在Bird类中实现的fly()方法,如下代码:

((Flyable)animals[2]).fly();

需要明白的是:经过(Flyable) 进行转化后的animals[2](Bird类的实例),仅有接口Flyable定义的Bird类中实现的fly()方法。

可以这样理解:

(1)Bird类实现了Animal接口和Flyable接口;

(2)变量animals 被声明成Animal接口类型,但是通过Bird类创建的实例对象animals[2],这个变量animals[2]就像是被封印了非Animal接口中定义的其它方法,仅能使用Animal接口中定义的在Bird类中实现的方法。

(3)通过Flyable接口进行强制转化通过Bird类创建的实例对象animals[2],就像是解封了Bird类中实现的Flyable接口中的方法(fly()方法),但是也同时封印了非Flyable接口中定义的其它方法(bark()和move()方法)。

2、接口的转换(向下)

package com.test;public class Trainer {// 定义一个属性,类型是Animal接口private Animal animal;// 动物园里的驯兽师类Trainer构造方法public Trainer(Animal an) {this.animal = an;}// 驯兽师的进行驯兽方法public  void train() {animal.bark();animal.move();}
}
package com.test;public class Zoo {public static void main(String[] args) {// 使用Animal接口类型声明animals数组// 数组animals的成员分别是实现了Animal接口的Dog、Cat、Bird类Animal[] animals = {new Dog(),new Cat(),new Bird()};// 创建动物园驯兽师类的实例对象Trainer trainer;for (Animal an : animals) {trainer = new Trainer(an);trainer.train();}}
}

前一部分的代码建立了类Dog、Cat、Bird都实现了Animal接口。

在驯兽师Trainer类中定义了Animal接口类型变量animal,通过构造函数Trainer(Animal an),传入的Animal接口类型变量animal,赋值给Trainer类中定义的私有变量animal(是Animal接口类型),在Tainer类的训练方法train()方法中执行Animal接口中定义的方法(bark()和move())。

在Zoo类中的main()函数中:

(1)定义了animals数组,数组类型是Animal,但是数组中的元素是都实现了Aniaml接口的Dog、Cat、Bird类的实例对象。这些对象都具有Animal接口中定义的方法(bark()和move())。

(2)创建驯兽师类Trainer的实例,传入给Trainer的实例的方法train()的实参是animals数组,其中的元素分别是Dog、Cat、Bird类的实例对象。根据传入的实参不同,执行不同的类的实例对象的方法(bark()和move())。

通过设计Trainer类,就不需要针对每个动物去创建对应的驯兽师类(DogTrainer、CatTrainer、BirdTrainer)了。

为了再增加其他动物,只要这个动物实现了Animal接口,就可以在Zoo类中创建相应的实例对象,加入到声明为Animal类型的数组animals中。Trainer类不用做任何修改,即可训练这个动物了,当然只能训练Animal接口中定义的、在该类中实现的动作(bark()和move())。

这样,未来仅需要修改Animal接口(丰富训练内容),及创建实现Animal接口的更多动物类,Trainer类和Zoo类中的代码不用做任何修改,动物园的动物们都可以得到驯兽师(Trainer类)的训练。

上面的阐述特别的啰嗦,只是这让我比较清晰地理解了上面代码的意义。

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

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

相关文章

Spring总结之构造注入

构造注入&#xff1a; Spring调用类的有参构造&#xff0c;在构造方法中给属性赋值 构造注入使用的是<constructor-arg>标签&#xff0c;一个<constructor-arg>标签表示构造方法的一个参数。 <constructor-arg>标签属性&#xff1a; name&#xff1a;表示构…

C 数据类型

在 C 语言中&#xff0c;数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间&#xff0c;以及如何解释存储的位模式。 C 中的类型可分为以下几种&#xff1a; 序号类型与描述1基本数据类型 它们是算术类型&#xff0c;包括整型…

pytest 教程

1. 安装pytest 目前我使用的python版本是3.10.8 pip install pytest命令会安装下面的包&#xff1a; exceptiongroup-1.2.0-py3-none-any.whl iniconfig-2.0.0-py3-none-any.whl packaging-23.2-py3-none-any.whl pluggy-1.4.0-py3-none-any.whl pytest-8.0.2-py3-none-any.…

线性代数笔记10--矩阵的四个基本子空间

0. 引入 矩阵 A m n A_{m \times n} Amn​ 1. 列空间 C ( A ) C(A) C(A)在 R m R^m Rm中 d i m ( C ( A ) ) p i v o t _ c o l u m n _ c n t r a n k ( A ) r dim(C(A))pivot\_column\_cnt rank(A)r dim(C(A))pivot_column_cntrank(A)r 2. 零空间 N ( A ) N(A) N(A)…

web自动化笔记十六:日志收集

日志的作用&#xff1a; -调试程序 -了解系统程序运行情况&#xff0c;是否正常 -系统程序运行故障分析与问题定位 -用来做用户行为分析的数据统计 日志级别&#xff1a;是指日志信息的优先级、重要性或者严重程度 DEBUG&#xff1a;调试级别&#xff0c;…

Kubernetes 外部 HTTP 请求到达 Pod 容器的全过程

文章目录 1、问题一2、HTTP 请求流转过程概述图3、详细过程分析4、容器技术底座5、问题二6、详细过程分析(补充) 1、问题一 当外部发送一个HTTP/HTTPS 请求到Kubernetes 集群时&#xff0c;它是如何达到 Pod 中的 container 的呢&#xff1f; 2、HTTP 请求流转过程概述图 3、…

Scrapy与分布式开发(2.8):布隆过滤器原理及应用

布隆过滤器原理及应用 定义 布隆过滤器&#xff08;Bloom Filter&#xff09; 是一种空间效率极高的概率型数据结构&#xff0c;用于测试一个元素是否在一个集合中。它的优点是空间效率和查询时间都远超过一般的算法&#xff0c;缺点是有一定的误识别率和删除困难。 原理 布…

【论文阅读】(DALLE-3)Improving Image Generation with Better Captions

&#xff08;DALLE-3&#xff09;Improving Image Generation with Better Captions 文章目录 &#xff08;DALLE-3&#xff09;Improving Image Generation with Better Captions简介Method实验 引用&#xff1a; Betker J, Goh G, Jing L, et al. Improving image generation…

【数据存储】大端存储||小端存储(超详细解析,小白一看就懂!!!)

目录 一、前言 二、什么是低地址、高地址 &#xff1f; 三、什么是数据的高位和低位 &#xff1f; 四、什么是大小端存储&#xff1f; &#x1f349; 小端存储详解 &#x1f352; 大端存储详解 五、为什么会有大小端存储&#xff1f; &#x1f34d;大端存储的优点 &#…

React | 低代码平台开发实践

⭐简单说两句⭐ 作者&#xff1a;后端小知识&#xff0c;CSDN后端领域新星创作者|阿里云专家博主 CSDN个人主页&#xff1a;后端小知识 &#x1f50e;GZH&#xff1a;后端小知识 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 前言 随着数字…

构造函数:初始化列表 篇

前言&#xff1a;为什么会出现初始化列表这个功能&#xff1f; 在学习初始化列表之前&#xff0c;我们通常在构造函数中为函数赋初值&#xff0c;但这行为并不能称为初始化。因为初始化具有唯一性&#xff0c;只能初始化一次&#xff0c;而构造函数体内可以多次赋值。因此我们…

[蓝桥杯 2020 省 B1] 整除序列

[蓝桥杯 2020 省 B1] 整除序列 题目描述 有一个序列&#xff0c;序列的第一个数是 n n n&#xff0c;后面的每个数是前一个数整除 2 2 2&#xff0c;请输出这个序列中值为正数的项。 输入格式 输入一行包含一个整数 n n n。 输出格式 输出一行&#xff0c;包含多个整数…

AI绘画丨超酷海盗女孩生成攻略

海盗在许多艺术作品中颠覆了历史上的负面模样&#xff0c;以正面的形象登场&#xff0c;这让许多较为年轻的人们对“海盗”这一职位充满憧憬。那么一个兼具野性与美丽的女性海盗该怎么生成呢&#xff1f;小编就带来了本次的生成关键词&#xff01; 关键词&#xff1a;pirate g…

在pytorch中利用GPU训练神经网络时代码的执行顺序并提高训练效率

在pytorch中利用GPU训练神经网络时代码的执行顺序并提高训练效率 在 PyTorch 中&#xff0c;大多数操作在 GPU 上默认是异步执行的&#xff0c;但这并不意味着它们是并行执行的。要理解代码是同步还是异步执行&#xff0c;以及是串行还是并行执行&#xff0c;我们需要考虑几个…

文件操作与IO(3) 文件内容的读写——数据流

目录 一、流的概念 二、字节流代码演示 1、InputStream read方法 第一个没有参数的版本&#xff1a; 第二个带有byte数组的版本&#xff1a; 第三个版本 搭配Scanner的使用 2、OutputStream write方法 第一个版本&#xff1a; 第二个写入整个数组版本&#xff1a; …

【Web】Java反序列化之CC7链——Hashtable

目录 链子原理分析(借尸还魂) 如何构造相等hash 又谈为何lazyMap2.remove("yy") 不过真的需要两个LazyMap吗 EXP 双LazyMap exp HashMap&LazyMap exp 链子原理分析(借尸还魂) 先看Hashtable#readObject origlength和elements分别是原始数组的长度和元素…

信号灯——进程通信——day16

今天主要讲一下信号灯&#xff0c;也是有名信号量&#xff0c;一共分为四个步骤&#xff1a;创建、销毁、申请以及释放 首先是创建&#xff1a; semget int semget(key_t key, int nsems, int semflg); 功能:创建一组信号量 参数:key:IPC对象名nsems:信号量的个数semflg:IPC_…

软件测试 - 测试用例基本理论

1. 概念 为了特定的目的(该目的是检验代码是否满足用户需求)而设计的文档&#xff0c;文档包含测试输入、执行条件、预期结果等。文档的形式一般是excel表格。 比如说我们买了一台电脑&#xff0c;新买的笔记本检查完外观之后第一步需要查看电脑是否能够正常开机&#xff0c;…

机器学习 | 超参数:交叉验证

机器学习算法中&#xff0c;超参数是一个非常重要的问题&#xff1b;     超参数&#xff0c;即&#xff1a;模型开始训练之前&#xff0c;设置好的参数 根据模型评估值&#xff0c;对超参数进行优化&#xff0c;选择最佳超参数值&#xff0c;以提高学习的性能和效果 对于…

爬虫案例二

想拿到电影天堂 其中一个下载地址如何实现呢 第一步电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com)电影天堂_电影下载_高清首发 (dytt89.com)电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com) 第一步 我直接打开 requests.exceptions.SSLError: H…