接口和多态

接口

概念

        接口是功能的集合,它同样是一种引用数据类型,可以把接口看作抽象类更为抽象的 "类"。

        接口只描述所应该具备的功能方法,但是没有具体的方法实现,即接口中具有的都是抽象方法,这些抽象方法的实现是由接口的实现类(相当于接口的子类)来完成,这样就可以将功能的定义和具体实现相分离,从而可以优化程序的设计。

        一切事物均有功能,即一切事物均有接口。

接口的定义

        它与类的定义不同,类定义使用的是关键字 class,而接口的定义使用的是关键字 interface。

public interface 接口名{抽象方法1;抽象方法2;抽象方法3;....
}

注意:

(1)接口中无法定义声明普通的成员变量;

(2)接口中的方法全部是 public abstract 修饰的可以公共访问的抽象方法,但是 public abstract 可以省略。

类实现接口

        类与接口之间不再是继承关系,类和接口的关系为实现关系,也就是类实现了接口。跟类与类之间的继承相似,但是使用的关键字不同,继承使用的关键字是 extends,但是实现使用的关键字是 implements。

        实现类(实现接口的类)实现接口,其实就相当于声明:"这个类具备了接口中的功能",也就是实 现类会继承接口中方法,这样一来实现类要么是个抽象类,要么实现类实现(重写)接口中的全部的抽象方法。

格式:

修饰符 class 类名 implements 接口{//对接口中所有抽象方法的重写
}

        在类实现了某个接口之后, 该类就会将接口中所有的抽象方法都继承过来,这个时候就需要对这些 继承而来的抽象方法进行重写,对这些功能是如何具体实现的进行完善,否则该类必须是一个抽象类 (抽象方法所在的类必定是抽象类)。

接口的注意事项

(1)接口中可以声明定义成员变量,但是必须使用固定的修饰符 -- public static final 修饰,而且改变 了在声明的时候就需要为其指定值。final 修饰的成员变量的值是不能够再改变,同时使用了 static 修 饰,因此我们也称接口中的变量为静态常量,与此同时变量名习惯性的使用全部大写的方式,如果这个 变量名是由多个单词构成的,为了区分多个单词,在多个单词之间使用下划线 "_" 连接。

public static final int PAGE_SIZE = 10;

(2)接口中定义的抽象方法都有固定的修饰符 -- public abstract,但是在实际声明接口中的功能方法的时候,我们可以把修饰符 public abstract 省略,或者省略其中的一部分,但是要注意的是,即使我 们省略了,它默认也是使用 public abstract 修饰符进行了修饰。

(3)接口跟抽象类一样不可以直接创建对象。

(4)接口的实现类必须对接口中所有的抽象方法进行重写,然后才能够通过接口的实现类创建接口的实例对象,否则由于实现类中该存在抽象方法,实现类是一个抽象类,还是无法创建实例对象。

接口的多实现

        解决类无法多继承的弊端,将多继承这种机制在 Java 中通过接口的多实现来完成。

示例:

public interface Fu1{void show1();
}public interface Fu2{void show2();
}public class Zi implements Fu1,Fu2{ //Zi 类同时实现了 Fu1 和 Fu2 接口public void show1(){//对 show1() 方法的重写}public void show2(){//对 show2() 方法的重写}
}

为什么我们要定义接口?

        接口是用来定义功能的,我们发现使用抽象也可以完成(使用抽象方法定义功能),但是由于类与类之间的单继承的局限性,如果我有一个类拥有多个功能,但是这多个功能定义在多个抽象类中,这个时候通过继承就无法实现了,因为我们无法让一个类同时继承多个抽象类,这个时候接口恰恰可以解决类单继承的弊端,因为接口可以多实现,我们可以将多个功能方法定义在多个接口中,然后让该类同时实现多个接口,即一个类可以同时实现多个接口。

Java中为什么不使用多继承?

        如果 Java 中使用多继承,当某个类同时继承自多个父类,而多个父类都拥有同一功能的方法(方法 声明相同但是实现不同),这样一来在子类中调用该功能方法的时候,会现在子类中寻找是否存在该声明的方法,如果不存在则到父类中寻找,但是由于子类同时继承自多个父类,而这多个父类的每一个类 中都存在这么一个方法,这个时候方法调用的时候就产生了不确定性,不知道具体调用哪一个父类中的方法才是正确,但是对于接口而言就不会出现这样的问题,因为接口中的方法只有声明部分,非抽象子类必然会对接口中的方法进行重写,方法在实际调用的时候调用的是实现类中的具体方法,不会产生调用的不确定性。

类继承类同时实现接口

        接口和类是同时实现产生关系的,而类与类之间是通过继承产生关系的,因此一个类在继承自一个 父类的同时,还可用实现多个接口,即子类继承自父类,拥有了父类一切可继承的属性和方法,同时还可以通过实现接口扩展一些额外的从父类那无法继承得到的功能方法,即让类继承自父类的同时,实现其他接口。

        接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。

示例:

public class Fu(){public void method(){//.......}
}public interface MyInterface(){void show();
}public class Zi extends Fu implements MyInterface{public void show(); //注意实现接口必须重写接口中所有的抽象方法
}

接口的多继承

        接口和接口之间也可以通过继承产生关系,即通过关键字 extends 进行继承,但是它跟类与类之间的 单继承又有所不同,接口和接口之间是可以多继承的。

public interface Fu1{void show1();
}public interface Fu2{void show2();
}public interface Fu3{void show3();
}public interface Zi extends Fu1,Fu2,Fu3{ //子接口同时继承自 Fu1,Fu2,Fu3这三个接口//该子接口同时拥有了 Fu1,Fu2,Fu3 这三个父接口的方法声明,但是没有具体实现
}

        在实际的开发的过程中,如果在多个接口中存在相同的方法,这个时候即使某个类同时实现了这具有相同方法的多个接口,也表示该类具有该功能,在类中只需要对这功能进行重写即可,在实际调用的时 候,调用的是重写的方法,因此不会产生调用的不确定性。

接口在开发中的它好处

1、接口的出现扩展了功能;

2、接口其实就是暴漏出来的规则;

3、接口的出现降低了耦合性。

总结

类与类之间是继承关系 ----- 单继承

类与接口之间是实现关系 ----- 多实现

接口与接口之家是继承关系 ----- 多继承

接口和抽象类的区别和联系

1、相同点:

(1)都位于继承体系的顶端,都是用来被其他类继承或者实现的。

(2)都不能够直接创建实例对象。

(3)都可以包含抽象方法,但是其子类或者实现类必须对所有的抽象方法进行重写,否则这个子类或者实现类还是一个抽象类(因为还具有没有重写的抽象方法)。

2、区别:

(1)抽象类中可以有具体的方法,接口只能包含抽象方法。

(2)一个类只能够继承自一个直接父类(可能是抽象类,也可以是非抽象类),但是却可以实现多个接口(同时拥有多个功能)。

(3)抽象类是某个事物应该具备怎么样的内容,继承体系使用is .. a关系。

(4)接口是某个事物额外的内容,继承体系是一种like .. a关系。

很多场景接口和抽象类都可以使用,那么该如何选择?

(1)优先使用接口,尽量避免使用抽象类。使用接口之后,我还能够实现其他接口以及继承自其他类, 但是使用抽象类之后就不能够再继承自其他类了。

(2)如果某个类既要定义行为功能(方法),又要定义一些公共的属性(成员变量),这个时候就需要使用抽象类因为接口中无法随意的定义普通的成员变量。

多态

        面向对象的三大特征:封装、继承、多态。(封装和继承前面已经说了)

概念

        Java 中可以从多个角度以多种形态去描述一个事物或者个体,子类类型的对象不仅仅能够使用子类类型去描述,还可以使用父类类型描述,即可以用父类类型去描述一个子类类型的对象,从中可以发现,要想让一个事物或者个体呈现出不同的形态,那么多种形态之间必须是有联系。

        在 Java 中多态的代码体现就是一个子类类型的对象既可以赋值给子类类型的变量,也可以赋值给父类类型的变量(使用父类类型的变量去引用一个子类类型的对象)。

多态最终体现: 父类类型的引用变量指向子类类型的对象。

多态的前提: 必须是父子关系的类或者类实现接口,否则就不能够又多态的说法。

多态的定义

(1)普通父子类之间的多态定义格式:

父类类型 变量名 = new 子类类型();

(2)抽象父类和子类之间的多态定义格式:

抽象父类类型 变量名 = new 子类类型();

(3)类实现接口之间的多态定义格式:

接口类型 变量名 = new 实现类类型();

多态的成员变量的特点

当子父类中出现同名的成员变量的时候,通过变量去调用对象的属性的规则如下:

编译时期: 引用变量能够调用哪些成员变量,参考的是引用变量类型所属的类中是否拥有可以被调用的成员变量,如果有,则可以正常编译,如果没有,则编译出错。

运行时期: 当编译成功之后,运行的时候,具体调用的是哪一个类中的成员变量,也是参考引用变量的类型。

总结: 编译看左边,运行也看左边,即多态中成员变量的编译和运行都看等号左边(变量的类型)。

示例:

public class Fu {String name = "爸爸";
}public class Zi extends Fu{String name = "儿子";
}public class Test {public static void main(String[] args) {//子类类型的变量指向子类类型的对象Zi zi = new Zi();//父类类型的变量指向子类类型的对象Fu fu = zi;System.out.println(zi.name);System.out.println(fu.name);}
}

运行结果:

多态的成员方法的特点

        当子父类或者实现类和接口中出现了相同的方法的时候(重写、覆盖、@Override),使用变量调用方法的规则如下:

编译时期: 引用变量能够调用哪些成员方法,参考的是参考的是引用变量类型所属的类中是否拥有可以被调用的成员方法,如果有,则可以正常编译,如果没有,则编译出错。

运行时期: 当编译成功之后,运行的时候,具体调用的是哪一个类中的成员方法,参考的是引用变量指向的对象的具体类型。

总结: 编译看左边,运行看右边。

示例:

public class Fu {public void fu(){System.out.println("父类中的方法!");};
}public class Zi extends Fu{public void fu() {System.out.println("子类重写父类中的方法!");}public void zi() {System.out.println("子类中的方法!");}
}public class Test {public static void main(String[] args) {//子类类型的变量指向子类类型的对象Zi zi = new Zi();//父类类型的变量指向子类类型的对象Fu fu = zi;zi.zi();fu.fu();}
}

运行结果:

多态的总结

        父类类型的变量可以指向子类类型的对象,能够调用哪些成员变量(属性)以及具体调用的是那个类中的成员变量都由变量的类型决定。

        父类类型的变量可以指向子类类型的对象,能够调用哪些成员方法看变量的类型,具体调用哪一个方法由对象的具体类型决定。

        对于成员变量我们以后都会使用关键字 private 修饰,因此对于成员变量我们不能够直接访问,因 此多态更多针对的是成员方法。

多态--转型

向上转型

        把子类类型的对象赋值给父类类型的变量,这就是向上转型,而我们学习的多态本身就是向上转型 的过程。

示例:

Zi zi = new Zi();
Fu fu = Zi;
父类类型 变量名 = new 子类类型();

向下转型

        把一个已经向上转换的子类类型的对象,使用强制转换的格式,将父类类型的引用转换为子类类型 的引用,这个过程我们称之为向下转型。

Fu fu = new Zi(); //将子类类型的对象赋值给父类类型的对象 -- 向上转型
Zi zi = (Zi)fu; //将符类型的引用转换为子类类型的引用 -- 向下转型
子类类型 变量名 = (子类类型)父类类型的变量; //前提是父类类型的变量指向的是子类类型对象

        如果我们直接创建一个父类类型的对象并使用父类类型的变量去引用,然后通过强制转换的方式让 子类类型的变量引用指向父类类型的变量引用,这个时候不能够向下转型,因为子类类型的引用变量是 无法指向父类类型的对象的。

Fu fu = new Fu();
Zi zi = (Zi)Fu(); //错误的用法

了解instanceof 关键字

        主要作用: 判断某个对象是否属于某一种引用数据类型,返回值是 boolean 类型的。

使用格式:对象 instanceof 数据类型。

示例:

Fu fu = new Zi(); //将子类类型的对象赋值给父类类型的对象 -- 向上转型
Zi zi = null;
//满足父类类型的变量指向的是子类类型的对象的时候,才进行向下转型
if(fu instanceof Fu){zi = (Zi)fu; //将符类型的引用转换为子类类型的引用 -- 向下转型
}

        当父类类型的变量指向子类类型的对象的时候,会发生向上转型的过程,这个时候子类类型对象的引用就会有子类类型转换为父类类型。        

        使用 instanceof 关键字对对象的类型进行判断,判断满足条件之后再进行向下转型,它可以有效的避免发生转换异常:java.lang.ClassCastException。

多态的好处和弊端

        向上转型的好处: 隐藏了子类类型,提高代码的扩展性。

        向上转型的弊端: 只能够使用父类共性的内容,而无法使用子类独有的功能(编译看变量的类型)。

        向下转型的好处: 可以使用子类特有的功能。

        向下转型的弊端: 万一转换的时候类型不匹配,容易发生 java.lang.ClassCastException 类型的转换异常,因此建议在转换之前进行对象的类型判断。

什么时候使用向上转型

        当我们不需要直接面对子类类型的时候,通过扩展性或者父类的功能就已经能够完成相应的逻辑操作了,这个时候就可以使用向上转型。

Person person = new Student();
//调用对象中的方法,会执行 Student 类中的 study() 方法,而不是 Person 类中的 study() 方法
person.study();

什么时候使用向下转型

        当需要使用子类特有的功能的时候,就需要使用向下转型了。

Student student = (Student)person; //向下转型
student.study(); //此时就可以调用 Person 类中独有的 study() 方法

面向对象的三大特性总结

        封装: 让对象的属性和方法的实现细节隐藏起来,只提供了对外的公共的访问方式,同时提高了代码的复用性。

        继承: 让类与类之间产生了关系,子类会自动继承父类一切可以继承的属性和方法,提高了代码的复用性,同时为多态提供了前提。

        多态: 配合继承(实现接口)和方法的重写,从而提高代码的复用性和扩展性,如果没有方法的重写,多 态则没有任何意义。

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

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

相关文章

美发店业务流程优化:SpringBoot管理系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…

Java | Leetcode Java题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; class Solution {public String validIPAddress(String queryIP) {if (queryIP.indexOf(.) > 0) {// IPv4int last -1;for (int i 0; i < 4; i) {int cur (i 3 ? queryIP.length() : queryIP.indexOf(., last 1));if (cur <…

汽车3d动效的作用!云渲染实现3d动效

在汽车营销领域&#xff0c;3D动效技术以其独特的视觉冲击力和交互体验&#xff0c;正成为吸引消费者注意力的新利器。而云渲染技术的应用&#xff0c;更是让这些动效如虎添翼&#xff0c;实现了高效、低成本的3D视觉内容制作与分享。本文将探讨汽车3D动效的作用&#xff0c;并…

java中的I/O(8个案例+代码+效果图)

目录 1.File类 1&#xff09;常用构造方法 1&#xff09;File(String pathname) 2&#xff09;File(String parent, String child) 3&#xff09;File(File parent, String child) 2&#xff09;常用方法 1&#xff09;boolean canRead() 2&#xff09;boolean canWrite() 3&am…

SiLM266x系列SiLM2661高压电池组前端充/放电高边NFET驱动器 为电池系统保护提供可靠性和设计灵活性

SiLM2661产品概述&#xff1a; SiLM2661能够灵活的应对不同应用场景对锂电池进行监控和保护的需求&#xff0c;为电池系统保护提供可靠性和设计灵活性。是用于电池充电/放电系统控制的低功耗、高边 N 沟道 FET 驱动器&#xff0c;高边保护功能可避免系统的接地引脚断开连接&am…

Linux云计算 |【第四阶段】RDBMS2-DAY2

主要内容&#xff1a; 数据读写分离概述、Maxscale实现数据读写分离、多实例配置、中间件概述 一、数据读写分离概述 数据读写分离&#xff08;Read/Write Splitting&#xff09;是一种数据库架构设计模式&#xff0c;旨在提高数据库系统的性能、可扩展性和可用性。通过将读操…

how to increase the height of the ps or cdm window

when the line reaches the bottom; directly pull up the top bar of the window after pulling down the bar

Llama-3.2-3B-Instruct PyTorch模型微调最佳实践

1 引言 Meta Llama 3.2多语言大型语言模型集合&#xff08;LM&#xff09;是一个1B和3B大小&#xff08;文本输入/文本输出&#xff09;的预训练和指令微调模型集合。Llama 3.2指令调整的纯文本模型针对多语言对话用例进行了优化&#xff0c;包括智能检索和总结任务。它们在常…

Vue组件继承与扩展

Vue组件继承与扩展 前言 与Class继承类似&#xff0c;在Vue中可以通过组件继承来达到复用和扩展基础组件的目的&#xff0c;虽然它可能会带来一些额外的性能损耗和维护成本&#xff0c;但其在解决一些非常规问题时有奇效。本文将通过一些非常规的功能需求来讨论其实现过程。 …

锐明Crocus系统 RepairRecord.do SQL注入漏洞

0x01 产品描述&#xff1a; 明锐技术是一家专注于AI和视频技术的商用车智能物联&#xff08;AIoT&#xff09;解决方案提供商&#xff0c;Crocus系统是其核心产品之一。该系统旨在利用人工智能、高清视频、大数据和自动驾驶技术&#xff0c;提高企业或车队的运营效率&#xff0…

python31_format方法的使用

format方法的使用 def str_format(c, d):"""格式化字符串函数本函数的目的是通过给定的参数c和d&#xff0c;去填充一个预设的字符串模板。模板中包含了{name1}和{name2}两个占位符&#xff0c;分别用参数c和d的值来替换。这个过程演示了Python中字符串格式化的…

AR虚拟试用,让网购不再只靠想象!

在数字化浪潮席卷全球的今天&#xff0c;电子商务已成为我们日常生活中不可或缺的一部分。然而&#xff0c;传统的网购体验往往受限于二维图片和文字描述&#xff0c;消费者在购买前只能依靠想象来构建商品的模样与适用性&#xff0c;这无疑增加了购物的不确定性和风险。幸运的…

基于卷积神经网络的脊柱骨折识别系统,resnet50,mobilenet模型【pytorch框架+python】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于卷积神经网络的脊柱骨折识别系统&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python&#xff0c;tkinter】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷…

Java面试宝典-Java集合02

目录 Java面试宝典-Java集合02 21、TreeMap 和 TreeSet 在排序时如何比较元素&#xff1f; 22、ArrayList 和 LinkedList 的区别是什么&#xff1f; 23、ArrayList 和 Vector 的区别&#xff1f; 24、队列和栈是什么&#xff1f;有什么区别&#xff1f; 25、Queue和Deque的区别…

版本控制系统Helix Core的常见使用误区及解决办法、实用工具及新功能介绍

日前&#xff0c;Perforce携手合作伙伴龙智一同亮相Unreal Fest 2024上海站&#xff0c;分享Helix Core版本控制系统及其协作套件的强大功能与最新动态&#xff0c;助力游戏创意产业加速前行。 Perforce解决方案工程师Kory Luo在活动主会场&#xff0c;带来《Perforce Helix C…

谈谈英国硕士毕业论文如何收集问卷数据

在之前几期文章中&#xff0c;英国翰思教育小编介绍了在写英国硕士毕业论文的时候如何设计问卷&#xff0c;以及设计问卷时需要注意的一些原则和细节。希望通过那些往期内容&#xff0c;可以帮助同学们正确认识毕业论文问卷设计&#xff0c;也可以帮助大家找到合适的问卷设计思…

vantUI用popup和picker和field做关键词搜索功能

<van-field class"mainFileCss" v-model"currentflowmeterLocation" left-icon"search" click"openPicker" center label"位号"placeholder"请输入位号"><template slot"button"></temp…

Linux查看下nginx及使用的配置文件

1、查到nginx进程 ps -aef | grep nginx2、通过进行pid查到nginx路径 pwdx <pid>3、根据路径得到配置文件 path***/nginx -t如下&#xff1a;

基于xml配置文件的Spring事务

在项目中对事务属性通常传播属性&#xff0c;回滚属性&#xff0c;隔离级别&#xff0c;超时属性都取默认值&#xff0c;只有只读属性会如下的配置&#xff1a; 什么意思&#xff1a;Service层你的类里的方法&#xff0c;以get&#xff0c;find&#xff0c;select等开头的方法是…

shell注意点

变量命名&#xff1a; 注意&#xff0c;变量名和等号之间不能有空格&#xff0c;定义变量时&#xff0c;变量名不加美元符号$&#xff0c;这可能和你熟悉的所有编程语言都不一样。同时&#xff0c;变量名的命名须遵循如下规则&#xff1a; 只包含字母、数字和下划线&#xff…