JAVA 基础 继承与抽象类
2021/4/18 20:25:38
本文主要是介绍JAVA 基础 继承与抽象类,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1 系统优化
2 继承
2.1 继承入门
概述:就是类与类之间的关系(子父类的关系),被继承的类常常将其称之为父类(基类或者超类),而继承父类的类常常将其称之为子类(派生类) 。子类可以直接去使用父类中非私有的成
员。
如何建立继承关系:使用extends关键字
格式:
public class 子类 extends 父类 {}
举例:
public class Student extends Person {}
2.2 好处和弊端
好处:
1、提高了代码的复用性
2、提高了代码的维护性
3、让类与类产生了关系,是多态的前提
弊端:增加了代码之间的耦合性
耦合:类与类之间的关联关系
开发原则:高内聚低耦合
那么我们应该什么时候去使用继承呢? 继承其实体现的是一种关系:“is a”(谁是谁的一种),只要是这种关系,我们就可以去使用继承。
2.3 继承的特点
特点:Java只支持单继承,不支持多继承,但是可以进行多层继承
为什么Java中不支持多继承?为了放置逻辑冲突
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7KaL32W-1618742814898)(images/image-20210418102304768.png)]
2.4 继承中成员的访问特点
2.4.1 成员变量
特点:变量的访问遵循就近原则
变量的访问查找顺序:
1、在子类的局部位置进行查找
2、在子类的成员位置进行查找
3、在父类的成员位置进行查找
注意:如果子类中出现了和父类同名的成员变量,此时在访问子类的成员变量的时候需要通过this关键字进行显式访问,如果要访问父类中的成员变量就需要通过super关键字进行显式访
问。
示例代码:
Fu类
public class Fu { // 父类 int num = 20 ; // 成员变量num20 }
Zi类
public class Zi extends Fu { // Zi继承Fu int num = 23 ; // 成员变量 public void show(){ // 成员方法 int num = 30 ; // 局部变量num System.out.println(num); // 输出变量num System.out.println(this.num); // 访问的Zi中的成员变量num System.out.println(super.num); // 访问的Fu中的成员变量num } }
2.4.2 this和super
this:本类对象的一个引用(通过this可以访问本类中的成员)
super:父类对象的一个引用(通过super可以访问父类中的成员)
this和super在访问成员时对应的格式
类成员 | this | 含义 | super | 含义 |
---|---|---|---|---|
成员变量 | this.变量名 | 访问本类的成员变量 | super.变量名 | 访问父类的成员变量 |
成员方法 | this.方法名(…) | 访问本类的成员方法 | super.方法名(…) | 访问父类的成员方法 |
构造方法 | this(…) | 访问本类构造方法 | super(…) | 访问父类构造方法 |
2.4.3 成员方法
访问特点:首先会在子类中查找对应的方法,如果有就直接调用;如果没有,从父类中进行查找,如果有就调用,如果没有就报错。
代码实现:
Fu类
public class Fu { public void show(){ // 成员方法 System.out.println("Fu....show..............."); } }
Zi类
public class Zi extends Fu { public void show(){ // 成员方法 System.out.println("Zi...............show.............."); } public void method(){ // 成员方法 this.show(); // 访问本类的show方法 super.show(); // 访问父类中的show方法 } }
测试类
public class ExtendsDemo01 { public static void main(String[] args) { // 创建子类对象 Zi zi = new Zi(); // 调用method方法 zi.method(); } }
2.4.4 方法重写以及应用场景
方法重写:子类中出现了和父类中一模一样的方法声明(返回值类型,方法名和参数列表都相同)这个现象我们将其称之为方法重写,也被称为方法覆盖,方法复写。
方法重载:在一个类中出现了多个同名的方法,但是它们参数列表不同,这中现象就称之为方法重载!
应用场景:当子类需要父类的功能,而功能主体子类有自己特有内容时,那么就可以重写父类中的方法,这样即沿袭了父类的功能,又定义了子类特有的内容。
案例演示:
public class iPearV1 { /* 1. 定义手机类 iPearV1 call(String name) : 打电话方法 smallBlack() : 语音助手 (speak english...) */ public void call(String name){ System.out.println("给" + name + "打电话"); } public void smallBlack(){ System.out.println("speak english..."); } }
public class iPearV2 extends iPearV1 { /* 2. 定义新手机类 iPearV2 call(String name) : 打电话方法 smallBlack() : 语音助手 (speak english... 说中文) 方法重写的应用场景: 当子类需要父类的功能,而功能主体子类有自己特有内容 可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容 */ public void smallBlack(){ super.smallBlack(); System.out.println("说中文"); } }
2.4.5 方法重写的注意事项
注意事项:
- 子类重写父类方法时,方法的访问权限不能比父类更低(一般情况下,子类在重写父类方法的时候,都是让子类的方法访问权限和父类的方法访问权限一致)
- 父类静态方法,子类也必须通过静态方法进行重写,父类非静态方法,子类不能通过静态方法进行重写
- 父类中私有的方法不能被重写
访问权限修饰符:
修饰符 | 同一个类中 | 同一个包中的子类与无关类 | 不同包中的子类 | 不同包中的无关类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
注:√表示可以访问,没有写表示不能访问
2.4.6 构造方法
方法特点:子类中所有的构造方法默认都会访问父类中无参数的构造方法
为什么构造方法的访问具有这样的特点呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。其实每一个构造方法的第一条语句默认都是:super() ;
针对Person类我们没有显示的指定父类,其实默认会继承Jdk中给我们提供的一个类Obejct(Object类是整个继承体系中的顶层父类,它往上就没有父类了)。
思考问题:如果父类中不存在无参数的构造方法,那么子类应该如何进行初始化呢?
1、在子类的构造方法中通过super显示的调用父类有参的构造方法
class Zi extends Fu { public Zi(int age){ super(age); } }
2、在子类的构造方法中通过this关键字调用本类其他的构造方法,而其他的构造方法中通过super在显示的调用父类有参的构造方法
class Zi extends Fu { public Zi(){ this(10); // super(); // 调用本类其他的构造方法 } public Zi(int age){ super(age); // 调用父类有参的构造方法 } }
注意事项:this(…)必须是构造方法的第一条语句,并且不能和super(…)共存
对原有的继承代码进行优化:
由于构造方法不能被继承,因此在子类中需要去指定自己特有的构造方法。在进行属性初始化的时候,需要通过super关键字显示的调用父类的构造方法进行初始化,而自己特有的属性,
直接通过this关键字进行赋值即可。
public class Student extends Person { // 子类自己特有的属性. private int score; public Student(){ // 无参构造方法 super(); // 调用了父类无参构造方法 } public Student(String name, int age, int score){ // Student的有参构造方法 super(name,age); // 通过super关键字显示的调用了父类有参的构造方法,完成name和age的初始化 this.score = score; // 把score参数赋值给Student的成员变量score } }
继承体系的内存图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zk96H7Dp-1618742814900)(images/image-20210418145621354.png)]
创建了一个子类的对象,是否同时创建了父类对象呢?没有创建父类对象
2.5 信息管理系统进行优化
分为两方面:
1、对Student和Teacher进行优化,将共性的内容抽取到Person类中,让Student和Teacher继承Person
2、对数据的封装才有有参构造方法进行完成
怎么实现?
思路:对StudentController中的inputStudentInfo进行修改,但是这种方式不符合我们开发的一个原则(开闭原则)。开闭原则:对修改进行关闭对扩展进行开放,最好是通过添加代码的
方式对系统进行扩展。那么实现的方式:在创建一个新的StudentController(OtherStudentController),然后在inputStudentInfo方法中进行数据的封装。
经过上述代码的处理以后,系统中目前就存在了两个和Student相关的Controller。
1、StudentController
2、OtherStudentController
而这两个Controller的大部分内容都是相同的,看到相同的内容继续进行优化,使用继承。因此需要编写BaseStudentController,让StudentController和OtherStudentController继承该
类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YgUZ6ffi-1618742814901)(images/image-20210418153426870.png)]
3 抽象类
3.1 概述
抽象方法:当我们不确定某一个方法的方法体内容的时候,此时就可以不用定义方法体**{}** ,那么这样的方法其实就是抽象方法,并且这个方法需要使用abstract关键字进行修饰。
抽象类:当一个类中出现了抽象方法,那么这个类就必须定义为抽象类。要把一个类定义成抽象类,就需要通过abstract关键字修饰这个类。
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
抽象类的定义格式:
public abstract class 类名{}
3.2 注意事项
注意事项:
1、抽象类不能被实例化
2、抽象类可以存在构造方法
3、抽象类的子类
- 可以是抽象类
- 也可以是具体的类
4、抽象类中可以没有抽象方法,但是如果有抽象方法,那么这个类必须是一个抽象类
3.3 应用场景
什么是设计模式?设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
简单理解:设计模式就是一套书写代码的风格,设计模式就是一套书写代码套路,自古套路得人心。Java语言中是存在23种设计模式。
使用设计模式的好处:
1、提高代码的复用性
2、提高代码的维护性
3、提高代码的扩展性
模板设计模式到底是什么?
思想:把抽象类整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法,让使用模板的类(继承抽象类的类)去重写抽象方法实现需求。
模板:是将一个事物的结构规律予以固定化、标准化的成果,它体现的是结构形式的标准化。
CompositionTemplate类
// 作文的模板类 public abstract class CompositionTemplate { // 模板方法:定义了代码结构的方法,我们可以将其称之为模板方法 public void write() { // 标题 System.out.println("<<我的爸爸>>"); // 作文的正文 body(); // 结束语 System.out.println("啊, 这就是我的爸爸...."); } // 作文的正文的抽象方法 public abstract void body(); }
TomCompositionTemplate类
// Tom的作文类 public class TomCompositionTemplate extends CompositionTemplate { // 重写父类方法 @Override public void body() { System.out.println("我的爸爸是李刚,相当的刚....."); } }
测试类:
TomCompositionTemplate tom = new TomCompositionTemplate() ; tom.write();
3.4 final关键字
final表示最终的意思,可以修饰的内容如下:
1、方法
- 特点:不能被子类重写
2、类
- 特点:不能被子类继承
3、变量
- 基本数据类型:变量的值不能被改变,只能被赋值一次,这样的变量就是常量(自定义常量),命名规范:字母都是大写,多个单词之间使用"_"进行隔开
- 引用数据类型:地址值不能被改变
final修饰的成员变量的初始化时机:
1、在定义的时候直接对其进行初始化
public class Student { final int a = 23 ; }
2、在构造方法执行完毕之前进行初始化
public class Student { final int a ; public Student() { a = 23 ; } }
4 总结
1、继承
2、抽象类
3、模板设计模式
4、final关键字
这篇关于JAVA 基础 继承与抽象类的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么修改Kafka的JVM参数?-icode9专业技术文章分享
- 2024-12-23线下车企门店如何实现线上线下融合?
- 2024-12-23鸿蒙Next ArkTS编程规范总结
- 2024-12-23物流团队冬至高效运转,哪款办公软件可助力风险评估?
- 2024-12-23优化库存,提升效率:医药企业如何借助看板软件实现仓库智能化
- 2024-12-23项目管理零负担!轻量化看板工具如何助力团队协作
- 2024-12-23电商活动复盘,为何是团队成长的核心环节?
- 2024-12-23鸿蒙Next ArkTS高性能编程实战
- 2024-12-23数据驱动:电商复盘从基础到进阶!
- 2024-12-23从数据到客户:跨境电商如何通过销售跟踪工具提升营销精准度?