• 非零基础自学Java (老师:韩顺平) 第8章 面向对象编程(中级部分) 8.8 面向对象编程 - 继承


    非零基础自学Java (老师:韩顺平)

    ✈【【零基础 快速学Java】韩顺平 零基础30天学会Java】

    第8章 面向对象编程(中级部分)

    8.8 面向对象编程 - 继承
    8.8.1 为什么需要继承

    举个栗子

    编写了两个类,一个时Pupil类(小学生),一个是Graduate(大学毕业生)。

    两个类的属性和方法有很多是相同的。

    → 继承(代码复用性)

    8.8.2 继承基本介绍和示意图

    继承可以解决代码复用,让编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。

    在这里插入图片描述

    8.8.3 继承的基本语法
    class 子类 extends 父类{
        
    }
    
    • 1
    • 2
    • 3
    • 子类会自动拥有父类定义的属性和方法
    • 父类又叫超类、基类
    • 子类又叫派生类
    8.8.4 快速入门案例

    学生类

    package com.dingjiaxiong.extend_.improve_;
    
    /**
     * ClassName: Student
     * date: 2022/9/2 22:33
     *
     * @author DingJiaxiong
     */
    
    //父类
    public class Student {
        //共有属性
        public String name;
        public int age;
        private double score; //成绩
    
        //共有的方法
        public void setScore(double score){
            this.score = score;
        }
    
        public void showInfo(){
            System.out.println("学生名" + name + " 年龄 " + age + " 成绩 " + score);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    小学生类

    package com.dingjiaxiong.extend_.improve_;
    
    /**
     * ClassName: Pupil
     * date: 2022/9/2 22:33
     *
     * @author DingJiaxiong
     */
    
    public class Pupil extends Student{
        public void testing(){
            System.out.println("小学生" + name + "正在考小学数学...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    大学生类

    package com.dingjiaxiong.extend_.improve_;
    
    /**
     * ClassName: Graduate
     * date: 2022/9/2 22:34
     *
     * @author DingJiaxiong
     */
    
    public class Graduate extends Student{
        public void testing(){
            System.out.println("大学生 " + name + "正在考高等数学");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试类

    package com.dingjiaxiong.extend_.improve_;
    
    /**
     * ClassName: Extends01
     * date: 2022/9/2 22:32
     *
     * @author DingJiaxiong
     */
    
    public class Extends01 {
        public static void main(String[] args) {
            Pupil pupil = new Pupil();
            pupil.name = "小学生1号";
            pupil.age = 11;
            pupil.testing();
            pupil.setScore(50);
            pupil.showInfo();
    
            System.out.println("========================");
            Graduate graduate = new Graduate();
            graduate.name = "大学生1号";
            graduate.age = 23;
            graduate.testing();
            graduate.setScore(80);
            graduate.showInfo();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    运行结果

    在这里插入图片描述

    8.8.5 继承给编程带来的便利
    • 代码的复用性提高了
    • 代码的扩展性和维护性提高了
    8.8.6 继承的深入讨论/细节问题
    • 类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

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

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

    • 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

    • super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

    • super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

    • java 所有类都是 Object 类的子类,Object是所有类的基类。

    • 父类构造器的调用不限于直接父类,将一直往上追溯直到 Object 类(顶级父类)

    • 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制

      想要A类继承B类和C类 → 【A继承B,B继承C】

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

    举个栗子

    顶级类

    package com.dingjiaxiong.extend_;
    
    /**
     * ClassName: TopBase
     * date: 2022/9/2 22:46
     *
     * @author DingJiaxiong
     */
    
    public class TopBase {//父类是Object
        public TopBase(){
            System.out.println("构造器TopBase()被调用...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Base类

    package com.dingjiaxiong.extend_;
    
    /**
     * ClassName: Base
     * date: 2022/9/2 22:45
     *
     * @author DingJiaxiong
     */
    
    public class Base extends TopBase{
        //4个属性
        public int n1 = 100;
        protected int n2 = 200;
        int n3 = 300;
        private int n4 = 400;
    
        //无参构造器
        public Base(){
            System.out.println("父类Base()构造器被调用");
        }
    
        //有参构造器
        public Base(String name , int age){
            System.out.println("父类Base(String name , int age)构造器被调用");
        }
    
        //有参构造器
        public Base(String name){
            System.out.println("父类Base(String name)构造器被调用");
        }
    
        public int getN4(){
            return n4;
        }
    
        public void test100(){
            System.out.println("test100");
        }
    
        protected void test200(){
            System.out.println("test200");
        }
    
        void test300(){
            System.out.println("test300");
        }
    
        private void test400(){
            System.out.println("test400");
        }
    
        public void callTest400(){
            test400();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    子类

    package com.dingjiaxiong.extend_;
    
    /**
     * ClassName: Sub
     * date: 2022/9/2 22:46
     *
     * @author DingJiaxiong
     */
    
    public class Sub extends Base{
        public Sub(String name , int age){
    //        super();//调用父类的无参构造器
    //        super("韩老师");//调用父类的Base(String name)构造器
            //调用父类的Base(String name , int age)构造器
            super("韩老师",30);
            System.out.println("子类Sub(String name , int age)构造器被调用");
        }
    
        public Sub(){
            super("Smith",10);
            System.out.println("子类Sub()构造器被调用");
        }
    
        当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
        public Sub(String name){
            super("tom", 30);
            System.out.println("子类 Sub(String name)构造器被调用....");
        }
    
        public void sayOk(){
            System.out.println(n1 + " " + n2 + " " + n3);
    
            test100();
            test200();
            test300();
    
            //不能直接test400();
            System.out.println("n4 = " + getN4());
            callTest400();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    测试类

    package com.dingjiaxiong.extend_;
    
    /**
     * ClassName: ExtendsDetail
     * date: 2022/9/2 22:45
     *
     * @author DingJiaxiong
     */
    
    public class ExtendsDetail {
        public static void main(String[] args) {
            System.out.println("=====第一个对象=====");
            Sub sub = new Sub();
            System.out.println("=====第二个对象=====");
            Sub sub2 = new Sub("Jack");
            System.out.println("=====第三个对象======");
            Sub sub3 = new Sub("King", 10);
    
            sub.sayOk();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果

    在这里插入图片描述

    8.8.7 继承的本质分析
    package com.dingjiaxiong.extend_;
    
    /**
     * ClassName: ExtendsTheory
     * date: 2022/9/3 10:28
     *
     * @author DingJiaxiong
     */
    
    public class ExtendsTheory {
        public static void main(String[] args) {
            Son son = new Son();
            //根据查找关系返回信息
            //1. 首先看子类是否有该属性
            //2. 如果子类有这个属性,并且可以访问,则返回信息
            //3. 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
            //4. 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object..
            System.out.println(son.name);
            System.out.println(son.getAge());
            System.out.println(son.hobby);
        }
    }
    
    class GrandPa{ //爷类
        String name = "大头爷爷";
        String hobby = "旅游";
    }
    
    class Father extends GrandPa{ //父类
        String name = "大头爸爸";
        private int age = 39;
    
        public int getAge(){
            return age;
        }
    }
    
    
    class Son extends Father{ //子类
        String name = "大头儿子";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    运行结果

    在这里插入图片描述

    【子类创建的内存布局】

    在这里插入图片描述

  • 相关阅读:
    请求服务器数据API
    arp 隔离
    dubbo漫谈(一)
    【Mindspore】GeneratorDataset 中source data 含有dict 应该如何处理
    驱动开发:Win10内核枚举SSDT表基址
    getid3 获取视频时长
    基于springboot的大学生体质测试管理系统-计算机毕业设计源码
    IDEA 高效插件工具
    万界星空科技MES系统软件体系架构及应用
    每日一题 2651. 计算列车到站时间
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/126883175