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,一经查实,立即删除!

相关文章

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…

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

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

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

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

阿里云 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重点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 判…

第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…

C#开发-集合使用和技巧(八)集合中的排序Sort、OrderBy、OrderByDescending

C#开发-集合使用和技巧&#xff08;八&#xff09;集合中的排序Sort、OrderBy、OrderByDescending List<T>.Sort()IEnumerable<T>.OrderBy()Enumerable<T>.OrderByDescending() 在C#中&#xff0c;List<T> 类提供了多种方法来进行排序&#xff0c;最常…

jax.nn.initializers.glorot_normal()

import jax import jax.numpy as jnp from jax import random import jax.nn.initializers as init# 设置随机数种子 key random.PRNGKey(42)# 定义权重的形状 shape (in_dim, out_dim)# 获取 Glorot 正态初始化函数 glorot_normal_init init.glorot_normal()# 初始化权重 w…

QT基础 - QMainWindow主窗口

目录 零. 简介 一. 菜单栏 二. 工具栏 三. 状态栏 四. 可停靠区域 五. 总结 零. 简介 QMainWindow 是 Qt 中用于构建主窗口的类。 它通常包含以下几个主要部分&#xff1a; 菜单栏&#xff1a;用于提供各种操作选项。工具栏&#xff1a;放置常用的操作按钮。中心区域&…

搭建Vue的环境

目录 # 开篇 步骤一&#xff0c;准备Vue 的环境 步骤二&#xff0c;下载Vue.js的包 步骤三&#xff0c;创建并打开写前端代码的文件夹 步骤四&#xff0c;在VSCode中引入Vue.js的包 步骤五&#xff0c;创建第一个vue.html Vue其他知识 Vue.config命令 # 开篇 介绍&…

详细分析Element Plus的el-pagination基本知识(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 需求&#xff1a;从无到有做一个分页并且附带分页的导入导出增删改查等功能 前提一定是要先有分页&#xff0c;作为全栈玩家&#xff0c;先在前端部署一个分页的列表 相关后续的功能&#xff0c;是Java&#xff0c;推荐阅读&#x…

数据结构:4.1.2二叉搜索树的插入

整个框架和FInd函数的实现是一样的&#xff0c;但是也有不同&#xff08;注意&#xff09; 35>30 向30的右子树 35<41 向41的左子树 35>33 向33的右子树&#xff0c;但33右边为空&#xff0c;所以35就挂在33的右边 因为要把35挂在33的右边&#xff0c;所以要把33的…

Solkane 冷媒性能计算软件-管路计算

下载 制冷管道设计 制冷管路的压降会降低制冷量&#xff0c;增大功耗。但不同部分的管路允许的压降的数量级是不同的。 制冷管路的压降不是唯一的考虑因素&#xff0c;制冷剂的流速往往比压降更重要。 制冷系统中&#xff0c;压缩机、阀、汽液分离器或其他附件上的连接件的尺…

VSCode 安装NeoVim扩展(详细)

目录 1、安装NeoVim扩展 2、windows安装Neovim软件 3、优化操作相关的配置&#xff1a; 5、Neovim最好的兼容性配置 6、技巧和特点 6.1 故障排除 6.2、Neovim 插件组合键设置 6.3、跳转列表 1、安装NeoVim扩展 在扩展商店搜索NeoVim&#xff0c;安装扩展 2、windows安装…