javaSE:继承

在谈继承之前,我们先观察下面这个代码: 

//定义一个猫类
class Cat {public String name;public int age;public float weigth;public void eat(){System.out.println(this.name+"正在吃饭");}public void mimi(){System.out.println(this.name+"正在咪咪叫");}
}
//定义一个狗类
class Dog {public String name;public int age;public float weigth;public void eat(){System.out.println(this.name+"正在吃饭");}public void bark(){System.out.println(this.name+"正在狗叫");}}
//测试类
public class Test{public static void main(String[] args) {Dog dog=new Dog();//定义一个狗对象dog.name="旺财";dog.eat();dog.bark();Cat cat=new Cat();//定义一个猫对象cat.name="咪咪";cat.eat();cat.mimi();}
}

上面代码中发现,在猫类和狗类中,有大量代码存在重复:

 public String name;public int age;public float weigth;public void eat(){System.out.println(this.name+"正在吃饭");}

那能不能将这些重复的部分进行抽取呢?面向对象的思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。

继承概念:

继承(inheritance):是面向对象程序设计使代码可以复用的重要手段,它允许程序员在保持原有类特性的基础上进行扩展和增加新功能。一个类继承另一个类,这样产生的类叫子类/派生类,被继承的类叫父类/基类/超类,继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用

例如:上面的猫类和狗类中,可以将共性进行抽取。然后采用继承的思想来达到共用。

//定义一个Animal类
class Animal(){public String name;public int age;public float weigth;public void eat(){System.out.println(this.name+"正在吃饭");}
}

继承的语法:

在猫类和狗类中继承Animal类,在java中要表示继承的关系,需要借助extends关键字,具体如下:

修饰符 class 子类 extends 父类{

}

 对猫类和狗类重新进行设计:让猫类和狗类都继承Animal类

//猫类
class Cat extends Animal{public void mimi(){System.out.println(this.name+"正在咪咪叫");}
}
//狗类
class Dog extends Animals{ public void bark(){System.out.println(this.name+"正在狗叫");}}

 1.子类会将父类中的成员变量或者成员方法继承到子类中了

 2.子类继承父类之后,必须要新添加自己特有的成员,体现出与父类的不同,否则就没有必要继承

父类成员访问:

1.子类中访问父类的成员变量:

1.1子类和父类不存在同名字的成员变量:
public class B {public int a=1;public int b=2;
}public class C extends B{public int c=3;public void func(){System.out.println(a);//访问从父类继承下来的aSystem.out.println(b);//访问从父类继承下来的bSystem.out.println(c);//访问子类自己有的c}
}

在子类中也可以通过this调用来访问父类的成员变量。

public class B {public int a=1;public int b=2;
}public class C extends B{public int c=3;public void func(){System.out.println(this.a);//访问从父类继承下来的aSystem.out.println(this.b);//访问从父类继承下来的bSystem.out.println(this.c);//访问子类自己有的c}
}

这样写代码和上面效果一样。 

1.2子类和父类存在同名的成员变量:
public class B {public int a=1;public int b=2;
}public class C extends B{public int c=3;public int a=100;//定义一个与父类同名的成员变量public void func(){System.out.println(a);//不知道是调用哪一个aSystem.out.println(b);//访问从父类继承下来的bSystem.out.println(c);//访问子类自己有的c}
}

我们在子类访问变量a时,不知道调用的哪一个a,但从运行结果:来看,这里调用的a是子类自己的a。

所以当父类和子类有同名的成员变量时:优先访问子类的。

但有的人想问,如果想要先调用父类的a呢?这里就要用到一个关键字super

格式:super . 父类的成员变量

super可以用来访问子类继承过来父类的成员

具体下面会讲到。

 

 成员变量访问遵循就近原则,子类有优先访问自己的,如果没有则在父类中找。

 2.子类中访问父类的成员方法:

2.1子类和父类不存在同名的成员方法:
//父类
public class B {public void methodA(){System.out.println("父类的methodA方法...");}
}
//子类
public class C extends B{public void methodB(){System.out.println("子类的methodB方法...");}
}
//测试类
class Test {public static void main(String[] args) {C c=new C();c.methodA();c.methodB();}}

 调用成员方法与调用成员变量的操作一样。

 子类和父类成员方法没有同名的情况下,在子类方法中同对象引用访问方法时,优先调用子类自己的,若子类没有则在父类中寻找,若父类也没有则会报错

2.2子类和父类存在同名的成员方法:
2.1子类和父类存在同名的成员方法(方法里的参数不一样):
//父类
public class B {public void methodA(char a){System.out.println("父类的methodA(char a)方法...");}
}
//子类
public class C extends B{public void methodA(){System.out.println("子类的methodA()方法...");}
}
//测试类class Test {public static void main(String[] args) {C c=new C();c.methodA();c.methodA('a');}}

父类的methodA(char a)方法和 子类的methodA( )方法,因为方法名相同,方法参数不同。所以构成了方法的重载

根据调用的方法以及传递的参数访问合适的方法,若没有找到该方法,则会报错。

2.2子类和父类存在同名的成员方法(方法里的参数一样):
//父类
public class B {public void methodA(){System.out.println("父类的methodA()方法...");}
}
//子类
public class C extends B{public void methodA(){System.out.println("子类的methodA()方法...");}
}
//测试类class Test {public static void main(String[] args) {C c=new C();c.methodA();}}

在测试类中调用methodA的方法,默认调用的是子类的methodA的方法。

如果想调用父类的methodA的方法就要用super关键字。super.methodA()

//父类
public class B {public void methodA(){System.out.println("父类的methodA()方法...");}
}
//子类
public class C extends B{public void methodA(){System.out.println("子类的methodA()方法...");}
//通过super来调用父类的methodA的方法public void methoda(){super.methodA();
}
//测试类class Test {public static void main(String[] args) {C c=new C();c.methodA();}}

 super关键字:

有时候在一些场景下,子类和父类可能存在同名的成员变量或者成员方法,如果想从子类中访问父类中同名的成员变量或者成员方法,直接访问是无法做到的,所以Java中提供了super关键字,它主要的作用:在子类中访问父类的成员变量或者成员方法。

在子类中:

1.super.父类成员变量

2.super.父类成员方法

可以通过上面两种方式来访问父类中的成员。

super只能指向子类的父类,不能指向子类的父类的父类。

super还有第三种方法:

如果在父类中有构造方法,当子类继承父类之后,子类需要显示的调用父类的构造方法,要先帮助父类的成员进行初始化。可以用super调用父类的构造方法进而对父类进行初始化

//父类
public class B {public String name;public int age;
//父类的构造方法public B(String name,int age){this.name=name;this.age=age;}
//子类
public class C extends B{
//子类显示调用父类的构造方法public C(String name,int age){super(name,age);//}
}
//测试类
class Test {public static void main(String[] args) {C c=new C("酷酷的森",19);}}

在使用super的时候,要注意:super在调用父类构造方法时,一定要在方法中的第一条语句,不然会出错。

1.super调用父类的构造方法时,必须在第一行。前面我们讲过this()调用构造方法时,也只能在第一行,所以super()和this()是不能共存的。

2.当没有提供任何的构造方法的时候,java中会提供默认的构造方法,如下:

//父类
public class B {
//默认提供的构造方法public B(){
}}
//子类
public class C extends B{
/默认提供的构造方法public C(){super();
}
}

子类对象中成员是由两部分组成,父类继承下来的以及子类新增加的部分,父子父子,肯定是先有父再有子,所以在构造子类的对象时,要先调用父类的构造方法,将父类继承下来的成员初始化完整,然后调用子类的构造方法,将子类自己新增加的成员初始化完整。 

 注意:

1.在public C方法中,你也可以省略super(),因为在若父类显式定义无参或者默认的构造方法时,在子类构造方法第一行默认有隐式的super()调用。调用基类的构造方法。

2.如果父类构造方法带有参数,此时需要用户显式定义构造方法,并在子类构造方法中选用合适的父类构造方法调用,否则编译出错。

3.在子类构造方法中调用父类构造方法,super()必须在子类构造函数第一条语句

4.this()和super()不能同时出现在同一个构造方法里面。

但是只要你写了一个构造方法,这个默认构造方法就不会提供。

 super和this:

相同点:

1.都是java中的关键字

2.都只能在非静态方法中使用,用来访问非静态的成员或方法

3.在构造方法中使用时,都只能在该方法中的第一条语句,且super()和this()不能同时存在。

不同点:

1.this是指当前对象的引用, 当前对象即调用实例方法的对象。super是在子类对象中调用从父类继承下来的那部分成员的引用

2.在非静态成员方法中,this调用的是本类的方法和属性,而super用来访问从父类继承下来的方法和属性。

3. 在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现

4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

再谈代码块:

之前讲过静态代码块,实例代码块,构造方法在没有谈继承的时候所执行的顺序。可以在(javaSE:对象和类(2))中复习

现在讲了继承,它们又是按照什么顺序进行执行的呢?

//父类
public class B {public String name;public int age;//父类构造方法public B(String name,int age){this.name=name;this.age=age;System.out.println("父类构造方法执行了....");}//父类静态代码块static{System.out.println("父类静态代码块执行了....");}//父类实例代码块{System.out.println("父类实例代码块执行了....");}
}
//子类
public class C extends B{//实例代码块{System.out.println("子类实例代码块执行了.....");}//构造方法public C(String name,int age){super(name,age);System.out.println("子类构造方法执行了.....");}//子类静态代码块static{System.out.println("子类静态代码块执行了....");}
//测试类
class Test {public static void main(String[] args) {C c=new C("酷酷的森",19);}}

运行结果:

可知:先执行父类和子类的静态,再执行父类的实例和构造,最后执行子类的实例和构造

 如果改一下代码,增加一个对象,又会有什么不同呢?

//父类
public class B {public String name;public int age;//父类构造方法public B(String name,int age){this.name=name;this.age=age;System.out.println("父类构造方法执行了....");}//父类静态代码块static{System.out.println("父类静态代码块执行了....");}//父类实例代码块{System.out.println("父类实例代码块执行了....");}
}
//子类
public class C extends B{//实例代码块{System.out.println("子类实例代码块执行了.....");}//构造方法public C(String name,int age){super(name,age);System.out.println("子类构造方法执行了.....");}//子类静态代码块static{System.out.println("子类静态代码块执行了....");}
//测试类class Test {public static void main(String[] args) {C c=new C("酷酷的森",19);System.out.println("============");C cc=new C("111111",19);}}

 运行结果:

可知:第二次实例化对象,父类和子类的静态代码块都不会执行。

访问限定符:

为了实现封装特性,java引入了限定访问操作符,主要限定:类或者类中的成员能否在类外或者其他包中使用。

 private修饰的成员,只能在当前类访问

default修饰的成员,只能在同一个包低下的类中访问

public修饰的成员,公共的,任何地方都能使用

protected修饰的成员,同一个包低下可以使用,但是不同包下,只有子类才能使用。

 继承方式:

1.单继承:

public class A{
....
}
public B extends A{
....
}

2.多层继承:

public class A{
....
}
public class B extends A{
....
}
public class C extends B{
....
}

但是多继承,也不能无限继承下去。一般不超过3层的继承关系

3.不同类继承同一个类:

public class A{
....
}
public class B extends A{
....
}
public class C extends A{
....
}

4.java是不支持多继承的:一个类继承有多个父类是不允许的

java不支持多继承,但是可以通过接口的修形式,支持多继承

 final关键字:

1.final 关键可以用来修饰变量、成员方法以及类。
2.final修饰的变量是常量,此时这个变量的值就不能被修改了

3.如果一个类不想被其他类继承,此时可以用关键字final来,修饰这个类,此时这个类就叫密封类,不允许被其他类继承。

4.final修饰方法,这个方法就不能被重写。

继承和组合:

组合和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

继承是is-a的关系:比如:猫是动物,狗也是动物

组合是has-a的关系或者是 a part of (一部分)的关系:比如:汽车有发动机,轮子还有车载系统。

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

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

相关文章

等保测评-第一级通用要求

安全物理环境 物理访问控制 机房出入口应安排专人值守或配置电子门禁系统,控制、鉴别和记录进入的人员 防盗窃和防破坏 应将设备或主要部件进行固定,并设置明显的不易除去的标识。 防雷击 应将各类机柜、设施和设备等通过接地系统安全接地。 防火 机房应设置灭火设备 …

【面试】TCP 与 UDP区别

一、TCP 与 UDP 对比 TCP 传输控制协议 TCP(Transmission Control Protocol),是面向连接的【3次握手,4次挥手】,提供可靠交付,具有错误恢复机制(如超时重传、校验和等)&#xff0c…

YoloV9改进策略:注意力篇|BackBone改进|自研像素和通道并行注意力模块(独家原创)

摘要 本文使用FFA-Net的注意力改进YoloV9,FFA-Net提出了通道注意力和像素注意力相结合的方式,提高Block的表征能力,我把这两种注意力结合起来改进YoloV8的BackBone,取得了非常好的效果,即插即用,简单易懂,非常适合大家入手。 论文翻译:《FFA-Net:用于单图像去雾的特征…

nccl 03 记 回顾:从下载,编译到调试 nccl-test

1, 下载与编译 1.1 源码下载 $ git clone https://github.com/NVIDIA/nccl.git 1.2 编译 1.2.1 一般编译: $ make -j src.build 1.2.2 特定架构gpu 编译 $ make -j src.build NVCC_GENCODE"-gencodearchcompute_80,codesm_80" A10…

qt pro工程文件通用宏定义

在 Qt .pro 文件中,有一些预定义的宏(或变量),它们代表了特定的路径或与项目、构建环境相关的信息。 以下是一些常用的 .pro 文件宏: 通用宏 $$PWD: 当前 .pro 文件所在的绝对路径。这是一个非常重要的宏,…

react笔记-05react扩展篇

react笔记-扩展篇 包括新用法和hooks 1. setState setState更新状态的两种写法: 1. setState({}, [() > {}]) 2. setState(() > {// 返回一个状态修改对象return {} }, [() > {}])1. 对象写法: ⚠️注意:react更新状态是异步的 …

探究布局模型:从LayoutLM到LayoutLMv2与LayoutXLM

LAYOUT LM 联合建模文档的layout信息和text信息, 预训练 文档理解模型。 模型架构 使用BERT作为backbone, 加入2-D绝对位置信息,图像信息 ,分别捕获token在文档中的相对位置以及字体、文字方向、颜色等视觉信息。 2D位置嵌入 …

Linux 查看进程 ps -ef | grep

说明 在 Unix 和 Linux 系统中,ps -ef 命令用于显示所有正在运行的进程的详细信息。而 grep 是一个强大的文本搜索工具,它允许你在输入流(比如来自文件或另一个命令的输出)中搜索特定的模式。 当你将 ps -ef 的输出通过管道 | 传…

装备制造行业数据分析指标体系

数字化飞速发展的时代,多品种、定制化的产品需求、越来越短的产品生命周期、完善的售后服务、极佳的客户体验和快速的交货速度等,使得装备制造行业的经营环境越来越复杂,企业竞争从拼产品、拼价格迈向拼服务,装备制造企业正处于数…

阿里云 debian10.3 sudo apt-get updat 报错的解决方案

阿里云全新的debian10.3(buster)镜像,却无法正常执行 sudo apt-get update。主要报错信息如下: Err:6 http://mirrors.cloud.aliyuncs.com/debian buster-backports Release404 Not Found [IP: 100.100.2.148 80] Err:3 http://mirrors.cloud.aliyuncs…

无引擎游戏开发(1):EasyX图形库引入 + 跟随鼠标移动的小球

来自bilibili up主的Voidmatrix的视频教程:【从零开始的C游戏开发】 一、图形库引入 EasyX在国内文档最多,而且功能函数齐全,最适合入门。 环境配置:vs2022 (官网下载免费版) 百度搜EasyX官方&#xff0…

后方穿行预警系统技术规范(简化版)

后方穿行预警系统技术规范(简化版) 1 系统概述2 预警区域3 预警目标4 预警条件5 指标需求1 系统概述 RCTA后方穿行预警系统工作在驾驶员有倒车意向的时候。在倒车过程中当驾驶员视线因周围障碍物被遮挡而产生碰撞风险时,系统通过光学信号对驾驶员进行提醒。 2 预警区域 RCT…

前端入门篇(五十二)练习6:transition过渡小动画

所以应该先找到第n个li,找到li再找img,li没有找错,底下又各自只有一个img,解决 ul li:nth-child(1) img { } 描述文字从下往上: 一开始描述也在框框下面,当hover时,translateY(0)&#xff0…

js处理数组的方法总结

本文总结了JavaScript操作数组的所有方法方式。包含了ES6新增的方法。会在操作方法上解释出现的版本。 内容较多,建议收藏查看。 push(): 在数组末尾添加一个或多个元素,并返回新的长度。 let arr [1, 2, 3]; let newLength arr.push(4, 5); console.…

【JS重点18】原型链(面试重点)

一:原型链底层原理 以下面一段代码为例,基于原型对象(Star构造函数的原型对象)的继承使得不同构造函数的原型对象关联在一起(此处是最大的构造函数Object原型对象),并且这种关联的关系是一种链…

CleanShot X for Mac v4.7 屏幕滚动长截图录像工具(保姆级教程,小白轻松上手,简单易学)

Mac分享吧 文章目录 一、下载软件二、部分特有功能效果1、截图软件的普遍常用功能(画框、箭头、加文字等)都具备,不再详细介绍2、ABCD、1234等信息标注(每按一下鼠标,即各是A、B、C、D...等)3、截图更换背…

SQL注入-下篇

HTTP注入 一、Referer注入 概述 当你访问一个网站的时候,你的浏览器需要告诉服务器你是从哪个地方访问服务器的。如直接在浏览器器的URL栏输入网址访问网站是没有referer的,需要在一个打开的网站中,点击链接跳转到另一个页面。 Less-19 判…

Oracle中先进先出数据结构的例子

在Oracle中,实现先进先出(FIFO)数据结构的一个典型例子可以通过设计和查询特定的表来完成。以下是一个简化的例子来说明这个概念: 1. 设计表结构 首先,我们需要一个包含“入队”时间戳的表来模拟队列的行为。以下是一…

Python部分库函数

目录 一、常规函数 元组相关函数 1.元组的创建 2.元组多变量赋值 列表相关函数 1.列表的创建 (1)将至于中括号中的、用逗号分隔开的一组数据赋值给一个变量,数据可以是多个也可以是一个 (2)使用list函数 &…

第29讲:Ceph集群使用RBD块存储设备与K8S的PV集成

文章目录 1.Ceph集群使用RBD块存储与K8S集成简介2.Ceph集群RBD块存储与K8S PV存储卷集成2.1.创建K8S集群PV使用的块存储2.2.创建K8S集群访问RBD块存储设备的认证用户2.3.将认证用户的Key存储在K8S Secret资源中2.4.在K8S集群的所有节点中安装Ceph命令2.5.创建PV及PVC资源使用RB…