我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java继承与组合

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java继承与组合

系列文章目录

你真的知道怎样用java敲出Hello World吗?—初识JAVA
你知道为什么会划分数据类型吗?—JAVA数据类型与变量
10 > 20 && 10 / 0 == 0等于串联小灯泡?—JAVA运算符

目录

1.继承

1.1Java中为什么有继承的概念

Java用继承将现实世界中多种多样的实体进行共性抽取,然后让实体继承共性,从而简化代码.比如,我们将猫和狗抽取出他们的共性—动物.

java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。

我们用下面的代码描述狗和猫.

从上述代码可以看出,狗类和猫类存在一段重复的代码,这就是他们的共性,我们对这些重复的代码抽取共性,然后定义一个新的动物类.如下图:

对描述狗和猫的代码使用继承方式重新设计:
在Java中如果要表示类之间的继承关系,需要借助extends关键字
在这里插入图片描述

注意:子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
以上过程便是面向对象思想中提出的继承的概念,专门用来进行共性抽取,实现代码复用.

1.2 继承的概念

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

例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。

上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类/超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态。

1.3 继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下:

修饰符 class 子类 extends 父类 {

}

注意:

  • 子类会将父类中的成员变量或者成员方法继承到子类中了
  • 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

1.4 父类成员访问

子类将父类中的方法和变量继承下来了,子类中能直接访问父类中继承下来的成员.

1.4.1 子类中访问父类的成员变量

自我优先原则:

  • 访问的成员变量子类中有,优先访问自己的成员变量。
  • 访问的成员变量子类中无,访问父类继承下来的,如果父类也没有定义,编译报错。
  • 访问的成员变量与父类中成员变量同(不考虑数据类型),优先访问自己的

子类和父类不存在同名成员变量


子类和父类存在同名成员变量.

同名时,非要访问父类成员变量,用super,可强制访问父类成员变量.

1.4.2 子类中访问父类的成员方法

成员方法名字不同:成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。

public class Base {public void methodA(){System.out.println("Base中的methodA()");}}public class Derived extends Base{public void methodB(){System.out.println("Derived中的methodB()方法");}public void methodC(){methodB(); // 访问子类自己的methodB()methodA(); // 访问父类继承的methodA()// methodD(); // 编译失败,在整个继承体系中没有发现方法methodD()}}

成员方法名字相同:子类对象访问父类与子类同名方法时,如果父类和子类同名方法但参数列表不同(重载),根据调用方法视传递的参数选择合适的方法访问,如果没有则报错

public class Base {public void methodA(){System.out.println("Base中的methodA()");}public void methodB(){System.out.println("Base中的methodB()");}}public class Derived extends Base{public void methodA(int a) {System.out.println("Derived中的method(int)方法");}public void methodB(){System.out.println("Derived中的methodB()方法");}public void methodC(){methodA(); // 没有传参,访问父类中的methodA()methodA(20); // 传递int参数,访问子类中的methodA(int)methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),父类的无法访问

由此可见,方法重载可以不在同一个类中.

//此处应有代码示范的图片(super构造方法)

1.5 super关键字

由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,直接访问是无法做到的,Java提供了super关键字,该关键字主要作用是:在子类方法中访问父类的成员.
有些书上说: super代表父类对象的引用这句话是错误的! !super其实就是一个非常简单的关键字,增加了代码的可读性!
super使用举例如下:

public class Father {int a;int b;public void methodA(){System.out.println("Father中的methodA()");}public void methodB(){System.out.println("Father中的methodB()");}}public class Father extends Son{int a; // 与父类中成员变量同名且类型相同char b; // 与父类中成员变量同名但类型不同// 与父类中methodA()构成重载public void methodA(int a) {System.out.println("Son中的method()方法");} // 与父类中methodB()构成重写(即原型一致,重写后序详细介绍)public void methodB(){System.out.println("Son中的methodB()方法");}public void methodC(){// 对于同名的成员变量,直接访问时,访问的都是子类的a = 100; // 等价于: this.a = 100;b = 101; // 等价于: this.b = 101;// 注意:this是当前对象的引用// 访问父类的成员变量时,需要借助super关键字// super是获取到子类对象中从父类继承下来的部分super.a = 200;super.b = 201;// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法methodA(); // 没有传参,访问父类中的methodA()methodA(20); // 传递int参数,访问子类中的methodA(int)// 如果在子类中要访问重写的父类方法,则需要借助super关键字methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),父类的无法访问到super.methodB(); // 访问父类的methodB()}}public class Father {public Father(){System.out.println("Father()");}

super有三种使用场景:

  • super.成员变量
  • super.方法名()
  • super()调用父类构造方方法

使用super时注意:

  • super只能在非静态方法中使用
  • super只能在子类方法中访问父类的成员变量和方法
  • super() 调用父类构造方法必须在子类中使用才能调用父类的方法和属性
  • super() 帮助子类调用父类构造方法初始化成员变量
  • super() 当父类有构造方法时,必须先帮父类完成构造方法, 子类才能完成构造方法,否则编译报错。
  • this () 和 super () 不能在同一个方法中,因为这两条语句都必须放在代码的第一行

面试问题:this和super的区别是什么?

1.6 super和this的区别

相同点:

  • super和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数
  • 都是Java中的关键字
  • 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  • 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

不同点

  • this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
  • 在非静态成员方法中:this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  • 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
  • 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

1.7 静态代码块和实例代码块在有继承关系时的执行顺序

我们先用一段代码演示一下在没有继承关系时的执行顺序:

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;System.out.println("构造方法执行");} {System.out.println("实例代码块执行");} static {System.out.println("静态代码块执行");}}public class TestDemo {public static void main(String[] args) {Person person1 = new Person("bit",10);System.out.println("============================");Person person2 = new Person("gaobo",20);}}//执行结果://静态代码块执行//实例代码块执行//构造方法执行//============================//实例代码块执行//构造方法执行

我们可以得出以下结论:

  • 静态代码块先执行,并且只执行一次,在类加载阶段执行
  • 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行

我们在来看在继承关系上的执行

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;System.out.println("Person:构造方法执行");} {System.out.println("Person:实例代码块执行");} static {System.out.println("Person:静态代码块执行");}}class Student extends Person{public Student(String name,int age) {super(name,age);System.out.println("Student:构造方法执行");} {System.out.println("Student:实例代码块执行");} static {System.out.println("Student:静态代码块执行");}}public class TestDemo4 {public static void main(String[] args) {Student student1 = new Student("张三",19);System.out.println("===========================");Student student2 = new Student("gaobo",20);}public static void main1(String[] args) {Person person1 = new Person("bit",10);System.out.println("============================");Person person2 = new Person("gaobo",20);}}//执行结果:Person:静态代码块执行Student:静态代码块执行Person:实例代码块执行Person:构造方法执行Student:实例代码块执行Student:构造方法执行===========================Person:实例代码块执行Person:构造方法执行Student:实例代码块执行Student:构造方法执行

得出以下结论:

  • 父类静态代码块优先于子类静态代码块执行,且是最早执行
  • 父类实例代码块和父类构造方法紧接着执行
  • 子类的实例代码块和子类构造方法紧接着再执行
  • 第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

1.8 protect

为了实现封装特性,Java中引入了访问限定符,主要限定:类或者类中成员能否在类外或者其他包中被访问。在程序设计时,类要尽量做到 “封装”,即隐藏内部实现细节, 只暴露出必要的信息给类的调用者.因此我们在使用的时候应该尽可能的使用比较严格的访问权限. 例如如果一个方法能用private, 就尽量不要用 public. 还有一种 简单粗暴 的做法: 将所有的字段设为private, 将所有的方法设为public. 不过这种方式属于是对访问权限的滥用,不建议这样使用.

默认就是不加任何访问修饰限定符,也可以叫做default.

这里我们重点讲protected在不同位置中的使用.
同一个类:

在这里插入图片描述
同一个包中的类:

  • 同一个包中的子类
  • 同一个包中的非子类

不同包的子类:

注意:不同包中的子类要通过super访问

不同包且不是子类:

那我们什么时候用private什么时候用public呢?
在考虑用哪一个限定符时,我们应该考虑该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用).

1.9 继承方式

在现实生活中事物的继承关系可能非常复杂且灵活,那么我们就需要对不同的继承关系分类.
我们举例写的类是现实事物的抽象. 而我们真正开发所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字

JAVA中的继承方式有以下几种:

注意:Java中不支持下面这种多继承方式,C++中支持.

1.10 final 关键字

上面我们提到可以用final关键字限制继承,下面我们来详细了解final.

  • 修饰变量或字段,表示常量(即不能修改)
final int a = 10;a = 20; // 编译出错

定义的同时可以不初始化,但是只能初始化一次.

final int a;a = 100;System.out.println(a);
  • 修饰类:表示此类不能被继承
final public class Animal {...}public class Bird extends Animal {...} // 编译出错Error:(3, 27) java: 无法从最终com.bit.Animal进行继

我们查看String字符串类可以看到,String字符串类是用final修饰的,不能被继承.

  • 修饰方法,表示该方法不能被重写

2. 组合

2.1 组合的概念

Java是一个面向对象的语言,每一个学习过Java的人都知道,封装、继承、多态是面向对象的三个特征。但组合并不是一种特性,它只是一种实现手段.组合也是一种表达类之间关系的方式, 也是能够达到代码复用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。
组合(Composition)体现的是整体与部分、拥有的关系,即has-a的关系.我们可以用xx是xx的一部分这样的语句描述组合中体现的关系.

继承(Inheritance)是一种联结类与类的层次模型,指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系,是一种is-a关系。

例如,我们用组合写一个汽车的代码表现这种关系,如下:

// 轮胎类class Tire{// ...} // 发动机类class Engine{// ...} // 车载系统类class VehicleSystem{// ...}class Car{private Tire tire; // 可以复用轮胎中的属性和方法private Engine engine; // 可以复用发动机中的属性和方法private VehicleSystem vs; // 可以复用车载系统中的属性和方法// ...} // 奔驰是汽车class Benz extend Car{// 将汽车中包含的:轮胎、发送机、车载系统全部继承下来}

2.2 组合和继承的区别

下面我们从以下几个方面区别组合和继承:

  • 表示关系上:
    继承表示对象之间是is-a的关系(可以用xx是xx描述),比如:狗是动物,猫是动物

组合表示对象之间是has-a的关系(可以用xx是xx的一部分描述),比如:零件是汽车的一部分

  • 代码复用上:
    继承:父类的内部细节对于子类是可见的,所以我们通常也可以说通过继承的代码复用是一种白盒式代码复用。(如果基类的实现发生改变,那么派生类的实现也将随之改变。这样就导致了子类行为的不可预知性;)

组合:通过对现有的对象进行拼装(组合)产生新的、更复杂的功能。因为在对象之间,各自的内部细节是不可见的,所以我们也说这种方式的代码复用是黑盒式代码复用。(因为组合中一般都定义一个类型,所以在编译期根本不知道具体会调用哪个实现类的方法)

  • 类的关系上:
    继承:在写代码的时候就要指名具体继承哪个类,所以,在编译期就确定了关系。(从基类继承来的实现是无法在运行期动态改变的,因此降低了应用的灵活性。)

组合:在写代码的时候可以采用面向接口编程。所以,类的组合关系一般在运行期确定。

建议在同样可行的情况下,优先使用组合而不是继承。因为组合更安全,更简单,更灵活,更高效,长期大量的使用继承会给代码带来很高的维护成本。


来源地址:https://blog.csdn.net/m0_74387295/article/details/129720227

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java继承与组合

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

多继承 , 组合 , 菱形继承 , 接口

一, 复习属性的的正确存放位置: 类中应该存储所有对象公共的内容 对象中存储都是每个对象独有的(都不同)初始化函数: 给对象的属性赋初值 , 可以保证只要对象被创建就一定有相应的属性 节省了重复代码绑定方法:
2023-01-31

day25-python之继承组合

1.上节回顾 1 class School: 2 x=1 3 def __init__(self,name,addr,type): 4 self.Name=name 5 self.Addr=a
2023-01-31

C++数据结构继承的概念与菱形继承及虚拟继承和组合分析

这篇“C++数据结构继承的概念与菱形继承及虚拟继承和组合分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++数据结构继承
2023-06-29

java继承与聚合的区别有哪些

Java中的继承和聚合都是实现代码重用的方式,但它们有一些区别。继承:1. 继承是通过创建一个类来继承另一个类的属性和方法。2. 子类继承了父类的所有非私有属性和方法。3. 继承是一种"is-a"关系,子类是父类的一种特殊类型。4. 子类可
2023-09-08

PHP 继承与多态,解构组合的艺术

PHP中的继承和多态是面向对象编程的重要组成部分,它允许程序员将代码组织成可重用且可维护的模块。本文将对继承和多态的概念、实现以及应用进行详细介绍,帮助读者深入理解这些关键概念。
PHP 继承与多态,解构组合的艺术
2024-02-14

javascript中什么是组合继承

javascript中什么是组合继承?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、说明用原型链实现原型属性和方法的继承,借用构造函数技术实现实例属性的继承。2、缺点组合模式
2023-06-15

python 继承与多重继承

当然,如果不支持python继承,语言特性就不值得称为“类”。派生类定义的语法如下所示: . . . 名称 BaseClassName 必须定义于包含派生类
2023-01-31

C++中继承与组合的区别详细解析

C++的“继承”特性可以提高程序的可复用性。正因为“继承”太有用、太容易用,才要防止乱用“继承”
2022-11-15

Java集合继承体系详解

Java的集合类是一种特别有用的工具,它可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如栈、队列等。Java集合还可以用于板寸具有映射关系的关联数组。java集合就像是一个容器,我们可以把多个对象(实际上是对象的引用,习惯上叫对
2023-05-30

Java继承

各位朋友们,大家好!今天我为大家分享的是Java上面一个很重要的知识点:继承,继承也被称为Java的灵魂之一。 文章目录 为什么要使用继承子类怎样继承父类在子类中如何访问父类的成员super关键字 当父类中有构造方法时this关
2023-08-17

JavaScript组合继承的示例分析

这篇文章主要为大家展示了“JavaScript组合继承的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript组合继承的示例分析”这篇文章吧。原型链继承父类实例作为子类的原型
2023-06-25

Maven的使用之继承与聚合

这篇文章主要为大家详细介绍了Maven的继承和聚合,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
2023-05-17

python3--类的组合,初始类的继承

面向对象的组合用法软件重用的重要方式除了继承之外还有另外一种方式,即:组合组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合例1#人狗大战classPerson:def__init__(self,name,sex,hp,ad
2023-01-30

javascript组合继承的意思是什么

这篇文章主要介绍“javascript组合继承的意思是什么”,在日常操作中,相信很多人在javascript组合继承的意思是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”javascript组合继承的意思
2023-06-20

java集合继承关系图分享

  面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。  数组虽然也可以存储对象,但长度是固定的;集合长度是可变的,数组中可以存储基本数据类型,集合只能存储对象。  
2023-05-30

Java之继承

继承 继承为什么使用继承继承是什么继承的语法访问父类成员访问父类成员变量访问父类成员方法 super关键字子类构造方法super和this异同分别的使用方法 继承的方式final关键字 作者简介: zoro-1,
2023-08-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录