【剧前爆米花--爪哇岛寻宝】抽象类和接口(上)——理论及逻辑理解

news/2024/11/25 5:58:12/

作者:困了电视剧

专栏:《JavaSE语法与底层详解》

文章分布:这是一篇关于抽象类和接口的文章,在本篇文章中我会介绍其相关的定义和语法,并且揭示接口和抽象类的运行逻辑,提高对面对象编程的理解。

 

目录

抽象类

抽象类概念及其语法

抽象类特性

抽象类作用

接口 

接口的概念和语法

接口的特性

接口和上转型在项目中被使用的逻辑(核心)

类,抽象类,接口的比较


抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
举个栗子:我现在有个动物类,动物都有一个行为那就是发出叫声,我可以定义一个Cat类继承这个动物类,然后Cat类在通过多态实现不同的行为——喵喵叫,此时如果我将动物类定义为一个普通类,那动物类就有一个叫声的行为,但是由于每个动物的叫声都不一样,那么此时这个动物类的叫声就发生了逻辑上的错误,即我不知道它是什么动物,无法判断它的叫声。
而如果我们把这个动物类设计成一个抽象类,那么我们就可以将这个叫声的方法设置成抽象方法,从而实现逻辑上的自洽,并且利用编译器的语法纠错提高程序的安全性。

抽象类概念及其语法

Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用 给出具体的实现体。
注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
abstract class Animal{int age;String name;String sex;//构造方法public Animal(int age, String name, String sex) {this.age = age;this.name = name;this.sex = sex;}public Animal(){}//抽象方法public abstract void eat();public abstract void speak();//普通方法public void sleep(){}
}

抽象类特性

1. 抽象类不能直接实例化对象
2. 抽象方法不能是 private
3. 抽象方法不能被finalstatic修饰,因为抽象方法要被子类重写
4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必      须要使用 abstract 修饰
5. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
6. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
解释:1.这一点是设计抽象类提高代码安全性的核心特性,就像我前文说的那样,有的时候一个类并不能表现一个特定的行为,但是当我们将它定义成普通类时,它就可以进行实例化,从而进行相应的行为,这在逻辑上并不自洽。
当我们用抽象类对其进行定义的时候,由于其不能进行实例化,所以就不会表现出相应的行为,减少了出错的可能,提高了代码的安全性。
2.重写是子类对父类的允许访问的方法的实现过程进行重新编写,用private修饰不论是不是抽象方法都不能进行重写。
abstract class Animal{int age;String name;String sex;//构造方法public Animal(int age, String name, String sex) {this.age = age;this.name = name;this.sex = sex;}public Animal(){}//抽象方法public abstract void eat();public abstract void speak();//普通方法private void sleep(){}
}class Cat extends Animal{@Overridepublic void eat() {}@Overridepublic void speak() {}@Overridepublic void sleep(){System.out.println("aaaaaa");}
}

这段代码会报错

4.由于抽象类并不能实例化对象,所以如果抽象类想要被使用的话就必须被继承,被继承到子类时也是抽象方法,所以如果子类不对其进行重写,则子类包含抽象方法,只能用抽象类来进行定义。

抽象类作用

使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题。
很多语法存在的意义都是为了 "预防出错", 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不就相当于常量嘛? 但是加上 fifinal 能够在不小心误修改的时候, 让编译器及时提醒我们。

接口 

接口的概念和语法

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。
Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类
Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到 多继承的目的。
接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字
public interface Code {public abstract void test1();public abstract void test2();
}interface Code_test1 extends Code{public abstract void test3();
}interface Code_test2 extends Code,Code_test1{public abstract void test4();
}
class Test1 implements Code,Code_test1,Code_test2{@Overridepublic void test1() {}@Overridepublic void test2() {}@Overridepublic void test3() {}@Overridepublic void test4() {}
}

接口的特性

1. 接口类型是一种引用类型,但是不能直接new接口的对象
2. 接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public   abstract(只能是public abstract,其他修饰符都会报错)
3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
4. 重写接口中方法时,不能使用默认的访问权限
5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static fifinal 变量
6. 接口中不能有静态代码块和构造方法
7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
8. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
9. jdk8中:接口中还可以包含default方法。

解释:

1.原因与抽象类类似,都是旨在提高代码的安全性,并且保证逻辑上的自洽。

2. 第二点和第五点中方法和变量前面的修饰符可加可不加,也可不加完,但在实际的项目中为了保证代码的简洁和统一,一般什么都不加。

public interface Code {int a=0;final int b=0;public final int c=0;public abstract void test1();public void test2();
}interface Code_test1 extends Code{abstract void test3();
}interface Code_test2 extends Code,Code_test1{void test4();
}
class Test1 implements Code,Code_test1,Code_test2{@Overridepublic void test1() {}@Overridepublic void test2() {}@Overridepublic void test3() {}@Overridepublic void test4() {}
}

 3.第四点中不能使用默认的类型是因为重写要求重写后的方法的访问权限不能低于重写前的方法,而在接口中默认的访问权限是public。

4.第七点编译后如图:

 可以看到后缀名也是.class。

接口和上转型在项目中被使用的逻辑(核心)

 接口的命名一般采用形容词性的单词。

我们来看一段代码:

public class Javabit_Code {public static void main(String[] args) {Animal cat=new Cat();Animal bird=new Bird();Action ac=new Action();ac.eat(cat);ac.eat(bird);ac.speak(cat);ac.speak(bird);ac.fly(new Bird());}
}class Action{public void eat(Animal animal){animal.eat();}public void speak(Animal animal){animal.speak();}public void fly(Iflying animal){animal.fly();}
}interface Iflying{void fly();
}abstract class Animal{int age;String name;String sex;//构造方法public Animal(int age, String name, String sex) {this.age = age;this.name = name;this.sex = sex;}public Animal(){}//抽象方法public abstract void eat();public abstract void speak();//普通方法public void sleep(){}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("吃猫粮");}@Overridepublic void speak() {System.out.println("喵喵叫");}
}class Bird extends Animal implements Iflying{@Overridepublic void eat() {System.out.println("吃鸟粮");}@Overridepublic void speak() {System.out.println("叽叽喳喳");}@Overridepublic void fly(){System.out.println("鸟在飞");}
}

在Action这个类中,我需要完成一些行为 ,但是此时由于我又不知道具体哪一个动物会被当做参数传进来,所以这里展现了多态的思想。

对于上转型来说,它提供了一种兼容,在Action类中的eat方法中,我需要传一个Animal的参数,这时我就可以运用上转型来完成这一点。

对于接口来说,它也提供了一种兼容,但和上转型又有点区别,上转型是“猫是动物”的关系即“is-a”的关系,而接口更像是“have-a”的关系,在本例中,他是只要实现了Iflying接口的类,其所实例化的对象就能当成参数,换个角度想,实现了Iflying接口就说明这个类实例化的对象会飞,而Action中的fly方法则是,只要是会飞的都可以实现这个方法。所以接口一般也用形容词进行命名。

这就是其中的逻辑关系。

类,抽象类,接口的比较

类就相当于一张盖楼用的图纸,我用这张图纸可以实例化一个楼。

抽象类就相当于没画完的图纸,这张图纸在某些地方,比如这栋楼的厕所建造时需要的信息没有画,只画了这个厕所要建在大致哪个位置,所以由于信息不全不能实例化一个楼。

接口,就相当于一套楼房大致框架的信息,你需要先把这些信息抄到一张图纸上,然后再在这张图纸上按照实际的需求进行补全,这样才能实例化一个大楼。

以上就是本篇文章的全部内容,如果对你有帮助还请三连,如有疏漏欢迎指正。


http://www.ppmy.cn/news/4352.html

相关文章

蓝桥杯嵌入式串口uart

文章目录前言一、板子串口原理图2.cubeMx配置3.波特率的简单讲解4.代码编写一、发送数据函数二、开启接收中断函数三、中断回调函数四、具体使用总结前言 本篇文章将带大家了解串口的编程,串口在比赛当中和实际工程中都是非常重要的,串口的难度也比较大…

《小白WEB安全入门》02. 开发篇

开发篇初识HTML潜在漏洞初识CSS潜在漏洞初识JS潜在漏洞初识后端潜在漏洞后端能做什么后端种类后端框架潜在漏洞本系列文章只叙述一些超级基础理论知识,极少有实践部分 本文涉及到的语言需自行掌握 初识HTML潜在漏洞 HTML指的是超文本标记语言(Hyper Tex…

面向智能化切片的服务化等级保障技术增强和研究

【摘 要】网络切片是5G垂直行业应用的重要使能技术,可以为不同应用场景提供差异化服务,切片服务等级保障使得运营商能够准确感知和评估各类业务的服务质量,以便进行服务质量的保障,然而,在切片的应用中,由于缺乏关于业务体验的实时监控,使运营商无法有效评估各类业务的…

猿如意|初识CSDN的开发者工具合集

前言: CSDN网站其实不仅仅有博客,虽然整个网站是基于博客开始的,但无疑博客是整个网站的魂。 那么,现在的CSDN还有第二个和第三个魂,就是云计算服务和猿如意了。 猿如意好像是CSDN5 6月份推出的,具体时间…

Linux--进程控制

前言: 这篇文章主要是讲解Linux下的进程控制,我们会学习到进程等待,进程程序替换, 微型shell,重新认识shell运行原理 。最后也编写了一个属于我们自己的shell,尽管功能不够齐全,但是还是感觉挺有意思&#…

重学c/c++之预处理

预定义符号 这些定义符号都是语言内置的 printf("%s\n",__FILE__);//绝对路径printf("%d\n",__LINE__);//代码所在的行号printf("%s\n",__DATE__);//Dec 17 2022(日期)printf("%s\n",__TIME__);//20:47:25(时间)printf("%s\n&qu…

更合理的 BBR

BBR 倾向于排空队列,甚至用特殊的 ProbeRTT 状态来排空自己产生的队列以测量 RTT,但这并不现实。一言以蔽之,BBR 无法实时跟踪现状,只靠拢理想。 若因背景流量造成 buffer 抖动,BBR 完全无法应对,其运行状…

大数据学习:学生排序

文章目录一、提出任务二、任务过程(一)准备数据1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录(二)实现步骤1、创建Maven项目2、添加相关依赖3、创建日志属性文件4、创建学生实体类5、创建学生映射器类5、创建学生归并器类6…