一篇文章让你了解Java中的继承

news/2024/12/22 14:00:12/

目录

  • 继承
    • 一.什么是继承
    • 二.为什么要使用继承
    • 三.继承的语法
    • 四.继承中有重复怎么办?
      • 1.**访问原则**
    • ==五.super和this==
    • 1.**this**
    • 2.**super**
    • 3.**super注意事项**
    • 4.**super和this异同点**
    • 六.构造方法的引入
      • 1.父类不带参数的构造方法
      • 2.父类带有参数的构造方法
    • 七.继承中的执行顺序
    • 八.继承方式
    • 九.final
    • 十.组合

继承

一.什么是继承

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

二.为什么要使用继承

在日常写代码的过程中,有时会敲写很多重复的代码,让自己的代码冗长无味,降低了可读性。当我们使用继承时,代码就变得简洁明了,更加美观。减少无用代码,提高开发效率。

我们举一个例子来说明:
我们在编写程序时,遇到一类相同的物时,通常需要挨个定义,如下
编写狗类时,我们需要狗拥有名字,年龄,毛色等的属性,也需要eat()等成员方法,以便后续使用
编写猫类时,我们也需要猫拥有名字,年龄,毛色等属性,也同样需要eat()等方法
这时我们发现狗和猫有许多重复的定义(共性)–名字,年龄,eat()等…
那我们可不可以使用一种语法来减少重复呢?这时就发明了继承。

在这里插入图片描述

三.继承的语法

修饰符 class 子类 extends 父类 {派生类        基类超类}

使用关键字extends来构写继承。
以猫和狗为例子,它们都属于动物,所以我将共性的类名称作Animal

//动物类——共性
class Animal{public String name;public int age;public String color;public void eat(){System.out.println(this.name+"正在吃饭");}
}
//狗类
class Dog extends Animal{public float weight;public void barks(){System.out.println(super.name+" 汪汪汪");}}
//猫类
class Cat extends Animal{public void sleep(){System.out.println(super.name+ " 正在睡觉");}
}

四.继承中有重复怎么办?

观察如下代码,我们可以看到在父类中有变量a,而子类中也定义了a。我们在

class Base{public int a = 10;public int b = 3;
}
class Derived extends Base{public int a = 20;public int c = 30;
public void menthod(){System.out.println(a);
}
}
public class menthod {public static void main(String[] args) {Derived derived = new Derived();System.out.println(derived.a);}
}

在这里插入图片描述

1.访问原则

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

1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
可以不可以打印出父类a的值? 这时就引出来我们的super和this

五.super和this

1.this

this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

2.super

该关键字主要作用:在子类方法中访问父类的成员。

以上面的代码为例,可以得到这样的一个图解:
在这里插入图片描述

3.super注意事项

1.super不能出现在static修饰的方法。
2.子类在继承父类之后,要使用构造方法将父类成员进行初始化。
3.在子类构造方法中,会默认调用父类的无参构造方法,这是编译器自动添加的。默认是super()。
4.如果父类的构造方法是有参数的,则子类也需要是有参数的
在调用父类时,要先将父类的成员变量初始化

4.super和this异同点

相同点
1:都是关键字。
2:都不能出现在静态构造方法中
3:this()和super()都需要位于构造方法中的第一行,也就意味着this()和super()不能同时出现

不同点
1:this是对当前对象的引用;
2:this符合就近原则访问成员变量,super访问父类成员变量。
3:this()用来调用子类构造方法,super()调用父类构造方法;
4:若存在继承,在子类的构造方法中,一定有super(),若自己不自定义,编译器也会也会自动添加,而this()则没有。

六.构造方法的引入

1.父类不带参数的构造方法

在子类构造方法中,会默认调用父类的无参构造方法,这是编译器自动添加的。默认是super();
我们在实例化对象后,该怎么写就怎么写

public class Main {public static void main(String[] args) {Dog dog = new Dog();dog.name = "小黄";dog.age = 1;}
}

2.父类带有参数的构造方法

这种情况就比较复杂了。蓝色背景的代码为新加入的构造方法。

在这里插入图片描述

观察代码,父类中自己定义了带参数的构造方法,这时我们在定义子类时,一定要先对父类的构造方法进行处理,这种处理通常是在自己的构造方法中默默使用super对父类构造方法进行涵盖,如下:

在这里插入图片描述
在这里插入图片描述
这里我们发现,在父类中使用this,在子类中使用super,这就跟上面解释的this和super的原理有关。
定义好之后,我们该如何使用呢?代码如下

public class Main {public static void main(String[] args) {Dog dog = new Dog("小黄",1);Cat cat = new Cat("喵喵",2);dog.eat();cat.sleep();}
}

运行效果如下:
在这里插入图片描述

七.继承中的执行顺序

先说结论

1.父类的实例,
2.父类的构造,
3.子类的实例
4.子类的构造。

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("静态代码块执行");}
}
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 testdemo {public static void main(String[] args) {Student student1 = new Student("张三",19);System.out.println("===========================");Student student2 = new Student("gaobo",20);}
}

在这里插入图片描述
通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

八.继承方式

单继承
在这里插入图片描述
多层继承
在这里插入图片描述
不同类继承同一类
在这里插入图片描述
但是不支持多继承
在这里插入图片描述

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会
更加复杂.
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了

如果想从语法上进行限制继承, 就可以使用 final 关键字

九.final

1:修饰变量,则该变量的值不能再被改变。
2:修饰类,则表示该类不能被继承
3:修饰方法,则该方法不能被重写

十.组合

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

通俗来说就是继承反转过来。

轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}

码字不易,感谢观看
如果对你有帮助的话,记得点赞👍评论+关注吧


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

相关文章

CentOS系统安装vsftpd

下载并安装vsftpd apt-get install vsftpd 安装后检查 service vsftpd status 修改配置文件(被动/匿名用户模式) vi /etc/vsftpd.conf anonymous_enableNO listenYES listen_port21 ascii_upload_enableYES ascii_download_enableYES local_enableYES guest_enable…

Webpack--动态 import 原理及源码分析

前言 在平时的开发中,我们经常使用 import()实现代码分割和懒加载。在低版本的浏览器中并不支持动态 import(),那 webpack 是如何实现 import() polyfill 的? 原理分析 我们先来看看下面的 demo function component() {const btn docume…

AI由许多不同的技术组成,其中一些最核心的技术如下

AI由许多不同的技术组成,其中一些最核心的技术包括: 机器学习:这是一种让计算机从数据中学习的技术,它可以根据已有的数据预测未来的趋势和行为。机器学习包括监督学习、无监督学习和强化学习等多种类型。深度学习:这…

el-form添加自定义校验规则校验el-input只能输入数字

0 效果 1 代码 {1,5}是用来限制小数点后几位的 addFormRules: {investAmount: [{ validator: checkInvestAmount, trigger: blur }], }, const checkInvestAmount (rule, value, callback) > {if (value ! && value ! null && value ! undefined) {if (/…

SQL审计是什么意思?目的是什么?有什么好处?

很多刚入行的运维小伙伴对于SQL审计不是很了解,不知道其是什么意思?使用SQL审计的目的是什么?使用SQL审计的好处有哪些?这里我们大家就来一起聊聊,仅供参考哈! SQL审计是什么意思? 【回答】&…

【左程云算法全讲3】归并排序与随机快排

系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考…

刷题笔记day15-二叉树层序遍历

层序遍历 /*** Definition for a binary tree node.* type TreeNode struct {* Val int* Left *TreeNode* Right *TreeNode* }*/import ("container/list" )func levelOrder(root *TreeNode) [][]int {// 思路1:此处肯定要使用队列result : …

数据库数据恢复—MSSQL报错“附加数据库错误823”如何恢复数据?

数据库故障&分析: MSSQL Server数据库比较常见的报错是“附加数据库错误823”。如果数据库有备份,只需要还原备份即可;如果无备份或者备份不可用,则需要使用专业的数据恢复手段去恢复数据。 MSSQL Server数据库出现“823”的报…