• Java学习 --- 面向对象之继承


    目录

    一、为什么需要继承

    二、什么是继承

    2.1、基本语法

    2.2、原理图

    三、继承注意事项

    四、继承的本质


    一、为什么需要继承

    问题:一个是Pupil类,一个是Graduate类,当两个类的属性和方法有很多是相同的应该怎么解决?

    Pupil类

    1. public class Pupil{
    2. private String name;
    3. private int age;
    4. private double score;
    5. public Pupil(String name, int age, double score) {
    6. this.name = name;
    7. this.age = age;
    8. this.score = score;
    9. }
    10. //具体功能
    11. public void testing(){
    12. System.out.println("学生:"+ name + "正在考试。。。");
    13. }
    14. //打印信息
    15. public void showInfo(){
    16. System.out.println("学生姓名:" + name + "\t年龄:" + age + "\t成绩:" + score);
    17. }
    18. }

    Graduate 类 

    1. public class Graduate {
    2. private String name;
    3. private int age;
    4. private double score;
    5. public Graduate(String name, int age, double score) {
    6. this.name = name;
    7. this.age = age;
    8. this.score = score;
    9. }
    10. //具体功能
    11. public void testing(){
    12. System.out.println("学生:"+ name + "正在考试。。。");
    13. }
    14. //打印信息
    15. public void showInfo(){
    16. System.out.println("学生姓名:" + name + "\t年龄:" + age + "\t成绩:" + score);
    17. }
    18. }

    上述代码中的属性以及功能都是重复的,代码复用性低。

    二、什么是继承

    继承可以解决代码复用,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

    2.1、基本语法

    class 子类 extends 父类{

    }

    1、子类会自动拥有父类定义的属性和方法

    2、父类又称超类或基类

    3、子类又称派生类

    2.2、原理图

     使用继承解决代码复用

    Student 类

    1. //是Pupil与Graduate的父类
    2. public class Student {
    3. private String name;
    4. private int age;
    5. private double score;
    6. public void setName(String name) {
    7. this.name = name;
    8. }
    9. public void setAge(int age) {
    10. this.age = age;
    11. }
    12. public void setScore(double score) {
    13. this.score = score;
    14. }
    15. public String getName() {
    16. return name;
    17. }
    18. public int getAge() {
    19. return age;
    20. }
    21. public double getScore() {
    22. return score;
    23. }
    24. //打印信息
    25. public void showInfo(){
    26. System.out.println("学生姓名:" + name + "\t年龄:" + age + "\t成绩:" + score);
    27. }
    28. }

    Pupil 类 

    1. //Pupil类继承Student类
    2. public class Pupil extends Student{
    3. //具体功能
    4. public void testing(){
    5. System.out.println("小学生:"+ getName() + "正在考试。。。");
    6. }
    7. }

    Graduate 类 

    1. //Graduate类继承Student类
    2. public class Graduate extends Student {
    3. //具体功能
    4. public void testing(){
    5. System.out.println("大学生:"+ getName() + "正在考试。。。");
    6. }
    7. }

    继承的好处:1、代码复用性提高了  2、代码的扩展性和维护性提高了

    三、继承注意事项

    1、子类继承了所有的属性和方法,私有属性不能在子类直接访问,但是非私有属性能在子类直接访问,通过父类提供公共的方法去访问私有属性和方法。

    Base 类

    1. //父类
    2. public class Base {
    3. //四种不同类型的属性
    4. public int n1 = 100;
    5. protected int n2 = 200;
    6. int n3 = 300;
    7. private int n4 = 400;
    8. //无参构造器
    9. public Base() {
    10. System.out.println("父类Base()构造器调用");
    11. }
    12. //对外提供一个公共的方法
    13. public int getN4() {
    14. return n4;
    15. }
    16. //四种不同类型的方法
    17. public void test1(){
    18. System.out.println("test1");
    19. }
    20. protected void test2(){
    21. System.out.println("test2");
    22. }
    23. void test3(){
    24. System.out.println("test3");
    25. }
    26. private void test4(){
    27. System.out.println("test4");
    28. }
    29. //对外提供一个getTest4公共的方法
    30. public void getTest4(){
    31. test4();
    32. }
    33. }

     Sub 类

    1. //子类
    2. public class Sub extends Base {
    3. //子类构造器
    4. public Sub() {
    5. System.out.println("子类Sub构造器调用");
    6. }
    7. public void sayOk(){
    8. //访问父类的非私有属性
    9. System.out.println(n1 + "\t" + n2 + "\t" + n3 );
    10. //访问父类的非私有方法
    11. test1();
    12. test2();
    13. test3();
    14. //使用父类提供的公共方法访问私有属性和方法
    15. System.out.println("n4="+ getN4());
    16. getTest4();
    17. }
    18. }

    SubTest 类 

    1. public class SubTest {
    2. public static void main(String[] args) {
    3. Sub sub = new Sub();
    4. sub.sayOk();
    5. }
    6. }

    运行结果:

     2、子类必须调用父类的构造器,完成父类的初始化

     3、当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果当父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不通过。

    场景一:不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器。

     调用子类的有参构造器

     运行结果: 

    场景二: 如果当父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不通过。

     子类编译会报错

     需要用super去指定

     运行结果

     4、如果要指定去调用父类的某个构造器,需要用super显示调用

    5、super在使用时,必须放在构造器第一行。注意:super只能在构造器中使用

     6、super()和this()都只能放在构造器第一行,所以这两个方法不能共存在一个构造器。

     7、Java所有类都是Object类的子类,Object是所有类的父类或基类。

    在idea中ctrl + H查看类的关系

     8、父类构造器的调用不限于直接父类,将一直往上追溯直到Object类。

    9、子类最多只能继承一个父类(直接继承),在Java中是单继承机制。

    10、不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。

    四、继承的本质

    1. public class ExtendsTheory {
    2. public static void main(String[] args) {
    3. Son son = new Son();
    4. System.out.println(son.age);
    5. System.out.println(son.hobby);
    6. }
    7. }
    8. class GrandPa{
    9. String name = "爷爷";
    10. String hobby = "旅游";
    11. }
    12. class Father extends GrandPa{
    13. String name = "爸爸";
    14. int age = 45;
    15. }
    16. class Son extends Father{
    17. String name = "儿子";
    18. }

    当子类对象创建好后,建立查找关系。

    1、首先看子类中是否具有需要的属性。

    2、当子类中有需要的属性,并且可以访问,就返回信息

    3、当子类中没有我们需要的属性,就需要到父类中查找是否有我们需要的属性,并且可以访问,就返回信息。

    4、当父类中没有我们需要的属性,就继续往上一级查找,直到Object类。

    内存图: 

  • 相关阅读:
    Sequential Allocation
    【MindSpore产品】relu函数和nn.relu出现环
    【更新中】MYSQL常用函数及方法
    Python学习笔记——存储容器
    常用SQL语句大全
    IDEA启动项目很慢,无访问
    快速使用UE4制作”大场景游戏“
    Android-线程池
    java 线程池
    Linux(Centos6)搭建ElasticSearch(图文教程)
  • 原文地址:https://blog.csdn.net/qq_46093575/article/details/126787802