JAVA如何利用接口实现多继承问题

hello,上文带大家学习了java中类的继承,我们可以创建一个父类,将类中的共性抽取出来,通过子类继承的方式来实现代码的复用。今天带大家学习不同类之间的另外几种关系,即多态抽象类和接口。

 多态的概念

多态,从字面意思去形象的理解可以解释为:针对不同的对象执行某一行为时,不同的对象会有不同的状态。

       比如猫和狗都是动物,他们都有进食这个行为但是当我们调用狗这个对象时,吃的是狗粮,而调用猫时,则会选择吃猫食。 

代码实操演示

class Animal{String name;int age;public  Animal(String name,int age){this.name=name;this.age=age;}public void eat(){System.out.println("正在吃饭");}}
class Cat extends Animal{public Cat(String name, int age) {super(name, age);//调用父类的构造方法}@Overridepublic void eat() {System.out.println(this.name+"正在吃猫食");;}
}
class Dog extends Animal{public Dog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println(this.name+"正在吃狗粮");}
}
public class Test {public static void eat(Animal a){a.eat();//这里放的是父类具体引用的是谁看传的对象}public static void main(String[] args) {Cat cat=new Cat("宝宝",3);Dog dog=new Dog("旺财",3);eat(dog);//传的狗eat(cat);//传的猫,这里其实就是动态绑定}
}

 这里还是解释一下,我们通过子类方法对父类的重写,后面又在Test类里创建eat()这里传的是Animal类,由于Animal是Dog和Cat的父类,所以后面我们在调用eat()时可以传Dog和Cat形,即小范围包含于大范围。这就是多态的含义。

类中方法的重写:

       重写:又称覆盖,子类可以对父类中的非静态,非private,非final,非构造方法的其他方法进行重新定义,注意:重写的方法返回值不能改变,方法的参数不能改变,方法名也不能改变。即方法的外壳,不变只对里面进行重新编写。我们可以根据子类的需要对父类中的方法进行重新定义。通常重写的方法会有一个标签 @override,上面的程序里有提及。

 这里可以对比记忆一下我们学过的重载:

注意:重写是对于子类和父类中研究的,即不同类之间,而重载是在一个类中实现了多个参数不同的同名的方法。 

动态绑定:即不能立马确定方法的行为,编译时不能确定,等到运行时才能世道方法到底调用的是哪个方法的类。

父类当中的向下转移和向上转移

就是将子类引用给父类来使用,将小范围赋值给大范围,但本质上仍然为子类对象。

所以运行的结果为宝宝吃猫食。

当然你也可以使用Dog类来进行向下转型,因为Animal也包含Dog。

  1. 直接赋值
  2. 方法的返回值
  3. 方法的参数

 直接赋值:

        Animal animal=new Cat("宝宝",10);

当做返回值:

向上转型的优点:代码更加灵活。

向上转型的缺点:无法调用子类中的特有方法。

那如果我们就是要调用子类中的特有方法怎么办呢?这就需要使用向下转型了。

向下转型:

我们可以使用关键字instanceof来对向下转型的对象做一层检验,保障了代码的安全性。

if(animal instanceof Cat){cat=(Cat)animal;cat.mew();

这里只有animal引用了Cat类的对象才执行if语句。

多态的优点

那么多态到底有什么优点呢,这里给大家总结一下,多态可以降低代码的圈复杂度,可以避免使用过多的if-else语句,其次,可拓展能力强需要新增一个类时,直接继承就好,需要注意构造方法么有多态性。

class B {
public B() {
// do nothing
func();
}
public void func() {
System.out.println("B.func()");
}
}
class D extends B {
private int num = 1;
@Override
public void func() {
System.out.println("D.func() " + num);
}
}
public class Test {
public static void main(String[] args) {
D d = new D();
}
}
// 执行结果
D.func() 0

 这里给大家一段有意思的代码,运行结果你猜对了吗,原因是new() D之后,第一步应该是调用父类的构造方法,即func(),但是构造方法在子类中被重写,所以调用的是子类中的func(),此时子类中的成员变量还没有赋值所以num仍然为0,所以运行结果为D.func() 0

抽象类即抽象方法的重写

其实,我们在最上面的代码中发现了一个问题,很多类由于不能将一个事物准确描述出来,针对不同的事物的行为不同,执行的方法也应该不同,比如Animal中的eat()并不能准确描述狗吃的狗粮,猫吃的猫粮,我们在狗类和猫类中还是要重写这个eat()方法,类似与Animal的这些类可以理解为抽象类。 

       抽象类,修饰限定符为public abstract,抽象类中的抽象方法(修饰符也是public abstract)类似与eat(),是不能有具体的定义的,原因很好理解,即使你写了,每个子类还得重写这个方法,我们只声明这个方法即可。注意:有抽象方法的类一定是抽象类,抽象类不一定含有抽象方法,抽象类也是类可以定义普通的成员变量,方法甚至是构造方法。(非常重要!!!!)

上代码理解一下:

//抽象类
public Abstract Animal{public abstract void eat();//抽象方法public abstract void look();//抽象方法
}
  1. 抽象类也不能实例化对象,因为抽像类无法完整描述一个事物,他只能被子类继承,然后子类必须将抽象类当中的抽象方法进行重写,否则编译报错,
  2. 抽象方法不能是 private 的,因为子类还要重写抽象方法的。
  3. 抽象方法不能被finalstatic修饰,因为抽象方法要被子类重写 

接口的概念:

       说到接口,我们第一想到的应该是USB接口插座...,这些当然都算接口,那么让我来说接口的特性的话,我觉得接口首先是一个封装好了的东西,并且它有着自己的功能,如果某个东西有了接口,那么他也应该具有接口的特性。

 

在java中接口是多个类的公共规范,是一种引用数据类型,接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。

interface A{public abstract void method1(); // public abstract 是固定搭配,可以不写public void method2();abstract void method3()
}

 接口不能直接使用,必须要有一个"实现类""实现"该接口,实现接口中的所有抽象方法。 这也比较好理解,毕竟接口只是实现 了某个特定的功能,并不能描述一个具体的对象。我们使用关键字implement将类和接口连接起来。

public class Animal implements IRunning{
// ...
}

 这里给大家举一个电脑的例子:

// USB接口
public interface USB {
void openDevice();
void closeDevice();
}
// 鼠标类,实现USB接口
public class Mouse implements USB {
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("鼠标点击");
}
}
// 键盘类,实现USB接口
public class KeyBoard implements USB {
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
public void inPut(){
System.out.println("键盘输入");
}
}
// 笔记本类:使用USB设备
public class Computer {
public void powerOn(){
System.out.println("打开笔记本电脑");
}
public void powerOff(){
System.out.println("关闭笔记本电脑");
}
public void useDevice(USB usb){
usb.openDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse)usb;
mouse.click();
}else if(usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard)usb;
keyBoard.inPut();
}
usb.closeDevice();
}
}
// 测试类:
public class TestUSB {
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
// 使用鼠标设备
computer.useDevice(new Mouse());
// 使用键盘设备
computer.useDevice(new KeyBoard());
computer.powerOff();
}
}

接口虽然是一种引用类型但是,他不能new(),必需通过引用类来重写接口中的所有方法,并且每个方法都默认为public abstract,也可以使用static和default修饰但是必须立即定义该方法,注意重写方法时一定要用public修饰。

public interface USB {
void openDevice(); // 默认是public的
void closeDevice(); // 默认是public的
}
public class Mouse implements USB {
@Override
void openDevice() {
System.out.println("打开鼠标");
}
// ...
}
// 编译报错,重写USB中openDevice方法时,不能使用默认修饰符
// 正在尝试分配更低的访问权限; 以前为public

 而且一个类是可以实现多个接口的,这也间接解决了java的多继承问题。

class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
interface IFlying {
void fly();
}
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
class Cat extends Animal implements IRunning {
public Cat(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name + "正在用四条腿跑");
}
}
class Fish extends Animal implements ISwimming {
public Fish(String name) {
super(name);
}
@Override
public void swim() {
System.out.println(this.name + "正在用尾巴游泳");
}
}

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

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

相关文章

Vue 3的Composition API和vue2的不同之处

Vue 3的Composition API是Vue.js框架的一个重要更新,它提供了一种新的组件逻辑组织和复用方式。在Vue 2中,我们通常使用Options API(data、methods、computed等)来组织组件的逻辑,但这种组织方式在处理复杂组件时可能会…

实体店好做还是电商平台好做?哪个发展前景较高?

我是电商珠珠 大部分人面对新的一年都会比较迷茫,想要创业会自己增加收入,却在开店和线上做电商这两者之间犹豫不决。不知道哪个更加合适自己,换句话来说,就是不知道哪个赔付率低一点。 现在这个行情,按照网友的说法…

C++ string类详解及模拟实现

目录 【本节目标】 1. 为什么学习string类? 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) 2. 标准库中的string类 2.1 string类(了解) 2.2 string类的常用接口说明(注意下面我只讲解最常用的接口) 3. string类的模拟实现 3.1string类常用…

Express学习(一)

Express Express简介 什么是Express 官方给出的概念:Express是基于Node.js平台,快速、开放、极简的web开发框架。 通俗的理解:Express的作用和Node.js内置的http模块类似,是专门用来创建Web服务器的。进一步理解Express 不使用E…

【软件使用】Markdown编辑器第一次使用介绍

【软件使用】Markdown编辑器第一次使用介绍 markdown格式支持的软件有:VS Code 和 Typora,CSDN写网页博文也是用的.md,CSDN能支持导入的文件也是以.md格式结尾的文件名。 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markd…

C语言——结构体(位段)、联合体、枚举

hello,大家好!我是柚子,今天给大家分享的内容是C语言中的自定义类型结构体、联合体以及枚举,有什么疑问或建议可以在评论区留言,会顺评论区回访哦~ 一、结构体 struct a.结构体声明 不同于数组的是,结构…

【CSP试题回顾】202212-2-训练计划

CSP-202212-2-训练计划 解题思路 输入和初始化: 首先,代码从输入中获取项目的截止日期和项目数量。然后,它初始化一个项目列表,每个项目都有其依赖项、被依赖的项目集合、完成时间、总完成时间(包括依赖链&#xff09…

【JavaSE】面向对象——多态性

多态性 多态性的概念 所谓多态性,理解为一个事物的多种形态。具体点就是去完成某个动作时,不同的对象会产生不同的状态。 多态性的好处 多态在Java中指的是父类的引用指向子类的对象,或者可以说是子类的对象赋给父类的引用。这样在我们的…

SpringBoot实现分页模糊查询

1. Navicat查询数据 Navicat中查询所有数据 SELECT * FROM sys_user;Navicat中查询前两条数据(俩种方式) SELECT * FROM sys_user LIMIT 2; //从0开始,第一个参数是起始位置即(pageNum-1)*pageSize,第二个参数是步长 SELECT * …

项目部署后 通过公网IP访问不到的问题解决

目录 1.检查项目是否在运行(第二行命令) 2.检查所用服务器防火墙是否打开 3.检查linux系统防火墙有没有打开 问题如图: 首先确保项目已经成功部署 1.检查项目是否在运行(第二行命令) 第一行命令是监听58080端口,我的项目是使用该端口 2.检查所用云服务器防火墙是否打开 我…

分享77个Html杂七杂八模板,总有一款适合您

分享77个Html杂七杂八模板,总有一款适合您 77个Html杂七杂八模板下载链接:https://pan.baidu.com/s/1-RyIKaxdCu3dbnlMFMwviw?pwd8888 提取码:8888 学习知识费力气,收集整理更不易。知识付费甚欢喜,为咱码农谋福…

每日好题3.5

前缀和 这个题目巨妙,打的时候没写出来,后面补题发现太牛了 思路:当前区间左端点 L L L ,当我们向右移动一次,就相当于,原式 - f ( L ) f ( L 1 e 18 ) f(L) f(L 1e18) f(L)f(L1e18),值就…

linuxOPS基础_服务器构成

服务器的重要结构组成 家用电脑组成: CPU、主板、内存条、显卡、硬盘、电源、风扇、网卡、显示器、机箱、键盘鼠标等等。 CPU CPU是电脑的大脑, CPU发展史: 32 位CPU:最大的内存寻址地址2^32,大约4G的大小。 CP…

CSS3新特性

简介 继CSS2之后,CSS3增加了很多新的特性,虽然W3C仍在规范中,但是很多新的CSS3属性已经在很多现代浏览器中得到了支持。 CSS3边框 在CSS3中,可以创建圆角边框,添加边框阴影,设置边框图片,利用…

计算机组成原理之机器:计算机系统的基本概念

计算机组成原理之机器 笔记来源:哈尔滨工业大学计算机组成原理(哈工大刘宏伟) Chapter1:计算机系统的基本概念 1.1 计算机系统简介 从物理构成的角度对计算机系统分层 计算机组成原理主要关注微体系结构(Mirco-arc…

【无标题】计算机主要应用于哪些领域

科学计算(或称为数值计算)、数据处理(信息管理)、辅助工程、生产自动化、人工智能。1、科学计算(或称为数值计算):早期的计算机主要用于科学计算。目前,科学计算仍然是计算机应用的一…

【原理图PCB专题】Allegro模块化移动器件报...has the LOCKED property怎么解锁?

在模块化原理图时,PCB也需要做一个模块.mdd文件。这时需要先画好图纸然后再制作模块化文件。 修改文件时会发现模块化器件报错,无法编辑模块内部器件和走线,器件和走线都被LOCKED,如下所示报错内容: Symbol "U1" Selected Cannot edit Symbol "U1". M…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:组件标识)

id为组件的唯一标识,在整个应用内唯一。本模块提供组件标识相关接口,可以获取指定id组件的属性,也提供向指定id组件发送事件的功能。 说明: 从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容…

代码随想录算法训练营第九天

28. 实现 strStr() &#xff08;本题可以跳过&#xff09; 方法&#xff1a; 方法一&#xff1a; 暴力法 i 表示最多能移动到n-m位置&#xff0c; 超过则退出循环。j表示haystack 初始位置k表示needle的初始位置如果haystack [j] needle[k]且 k<m 则 j, k; 如果 km 则返…

OJ输入问题+准备

写在之前&#xff1a; 发现题目输入是这样的&#xff1a; 我的问题&#xff1a;如何通过空格分割这些输入的字符串并分别保存&#xff01;&#xff01;&#xff08;C语言scanf好解决一点但我选择C....&#xff09; C引入了ostringstream、istringstream、stringstream这三个类…