• 继承 Inheritance


    继承

    前言: 本文 主要内容为 继承 。

    面向 对象 的 三大特征

    1.封装:

    指隐藏对象的属性和实现细节,仅对外提供公共访问方式

    简单的来说就是我将不想给别人看的数据,以及别人无需知道的内部细节, “锁起来” ,我们只留下一些入口,使其与外部发生联系。

    2.继承 :

    继承就是在一个已有类的基础上派生出新类(例如动物类可以派生出狗类和猫类),子类继承父类的特征和行为,使得子类对象(实例)

    具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为

    提高了代码的复用性,提高了代码的维护性(通过少量的修改,满足不断变化的具体要求),让类与类产生了一个关系,是多态的前提。

    但是缺点也很显著:让类的耦合性增强,这样某个类的改变就会影响其他和该类相关的类。

    特点:Java只支持单继承,不支持多继承(C++支持),但是Java支持多层继承(继承体系)形象的说就是:儿子继承爸爸,爸爸继承爷

    爷,儿子可以通过爸爸继承爷爷。

    3.多态:

    多态是同一个行为具有多个不同表现形式或形态的能力,例如:黑白打印机和彩色打印机相同的打印行为却有着不同的打印效果,

    • 对象类型和引用类型之间存在着继承(类)/ 实现(接口)的关系;
    • 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
    • 如果子类重写了父类的方法,最终执行的是子类覆盖的方法,如果没有则执行的是父类的方法。

    上面 先 提出 概念 那么 我们 来 学习 下我们 的 继承

    继承

    1.为什么 要需要 继承继承

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

    比如:狗和猫,它们都是一个动物。

    使用Java语言来进行描述,就会设计出:

    class Dog {
       String name;
       int age;
            public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    // 狗  能 看 家 特有的 方法
         public void Special() {
             System.out.println(name + "正在看 家");
         }
     }
     
     class Cat {
         String name;
         int age;
     
         public void eat() {
             System.out.println(name + "嗷嗷炫");
         }
     
         // 猫 能 爬树  特有 的 方法
         public void ClimBtree() {
             System.out.println(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

    ​  

    这里 我们 就 将 这个 狗 和 猫 ,用 代码 描述 出来 了 ,但 仔细 观察 ,可以发现 它们之间会有重复的 属性,那么 能否 将它们 共有 的 属性 抽离出来 呢 ?

    在这里插入图片描述


    这里 就 需要使用我们的 继承 ,继承 就是 专门用来进行共性抽取,实现代码复用。

    2.继承概念

    概念:

    继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加

    新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题

    是:共性的抽取,实现代码复用。

    下面 就来 演示 一下 。

    1.对 Dog he Cat 进行 共性 的 抽离 。

    抽离前:

    class Dog {
        String name;
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    
        // 狗  能 看 家 特有的 方法
        public void Special() {
            System.out.println(name + "正在看 家");
        }
    }
    
    class Cat {
        String name;
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    
        // 猫 能 爬树  特有 的 方法
        public void ClimBtree() {
            System.out.println(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

    抽离后:

    class Animal{
        String name;
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        } 
    }
    class Dog extends Animal {
       
    
        // 狗  能 看 家 特有的 方法
        public void Special() {
            System.out.println(name + "正在看 家");
        }
    }
    
    class Cat extends Animal{
    
    
        // 猫 能 爬树  特有 的 方法
        public void ClimBtree() {
            System.out.println(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


    对比一下 : 我们 抽离 共性 前 和 抽离 恭共性 后, 可以 发现 有明显的 不用 ,这里我们 多出 了 一个 类 Aniam(动物) 还多出 了 一个

    关键字 extends , 这里我们 的 Anialm 就是 父类 也可 叫 基类 或 超类 , 这里的 Dog 和 Cat 就是 我们的 子类 或 派生类 。

    在这里插入图片描述

    下面 就来 瞧一瞧 语法 , 其实 就是 类A extends 类 B

    3.继承 语法

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

    修饰符 class 子类 extends 父类 {
     // ... 
    }
    
    • 1
    • 2
    • 3


    注意:

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


    下面就来 稍微使用 一下 。

    class Animal {
        String name;
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    }
    
    class Dog extends Animal {
    
    
        // 狗  能 看 家 特有的 方法
        public void Special() {
            System.out.println(name + "正在看 家");
        }
    }
    
    class Cat extends Animal {
    
    
        // 猫 能 爬树  特有 的 方法
        public void ClimBtree() {
            System.out.println(name + "正在 爬树 ");
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.age = 20;
            dog.name = "小黑";
            dog.eat();
            Cat cat = new Cat();
            cat.age = 20;
            cat.name = "小兰";
            cat.eat();
            // 除了 掉父类 中的 字段 或方法 ,同样 也可 以掉 本身的
            dog.Special();
            cat.ClimBtree();
        }
    }
    
    
    • 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


    在这里插入图片描述


    使用完 来看 几个 小细节 :

    1.java 中 只能 继承一个 类 。

    在这里插入图片描述

    这里 就 是 想 让 Dog 这个 类继承 动物 类 ,和 猫类 ,可发现是 不行的 。

    2.父类和 子类 之间 的 方法 是可以 构成 重载 的 。

    啥意识 呢 ?

    这里 来看 :

    在这里插入图片描述

    3.子类 拥有 父类 同名字段

    class Animal {
        String name = "呜啦啦";
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    
        public void func() {
            System.out.println("测试 方法 一 ");
        }
    }
    
    
    class Cat extends Animal {
    
    String name = "小 黑 猫 ";
        // 猫 能 爬树  特有 的 方法
        public void ClimBtree() {
            System.out.println(name + "正在 爬树 ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    这里我们 的 Cat 继承 了 Animal , 但是 Cat 中 也有 name ,那么 此时 name 是 子类的 小黑猫 ,还是 父类的 呜啦啦 呢 ?

    在这里插入图片描述

    可以发现 打印的 是 我们的 小黑猫, 这里 我们的 可以得到 结论 : 如果访问的成员变量子类中有,优先访问自己的成员变量

    这里 直接 抛出 总结 :

    在子类方法中 或者 通过子类对象访问成员时:

    如果访问的成员变量子类中有,优先访问自己的成员变量。

    如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。

    如果访问的成员变量与父类中成员变量同名,则优先访问自己的。

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

    4.对于父类的 private 的字段和方法, 子类中是无法访问的.

    注意: 这里 是 被继承 了 但 访问 不了。

    在这里插入图片描述


    可以 看到 我们 通过 dog. 找不到 name 和 age ,那么 要如何 访问 到 name 和 age 呢 ??

    我们不是 学过 封装 吗 , 提供 get 和 set 方法 不就 ok 了 。

    class Animal {
        private String name;
        private int age;
    
        private void eat() {
            System.out.println(name + "嘎嘎炫");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    class Dog extends Animal{
        public void  func(){
            System.out.println("测试方法 ");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.setAge(20);
            dog.setName("小黑");
            System.out.println("姓名 " + dog.getName() +" 年龄" + dog.getAge() );
    
        }
    }
    
    
    • 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


    在这里插入图片描述

    super关键字

    由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,

    Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。

    1.super.data;调用 父类的成员属性

    刚刚我们的 几个 细节 当中 是不是 有 一个 , 子类 拥有父类 同名 字段 , 我们 想要 打印 父类的 字段 就可以 通过 我们的 super 来 完成 。

    class Animal {
        public String name = "小黑";
        public int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷的吃 ");
        }
    }
    
    class Dog extends Animal {
        public String name = "小红";
    
    
        public void func() {
            System.out.println(name);
            
            System.out.println(super.name);
        }
    }
    
    
    public class Main {
    
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.func();
        }
    }
    
    • 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

    在这里插入图片描述

    使用 super 调用 父类的 字段
    在这里插入图片描述


    2.super 第二种 用法 : 子类 构造对象 时 会 通过 super 帮助 父类 构造 。


    之前我们 学习 类的 构造方法,是不是 说过 ,对象是 通过 构造方法 才 能产生 ,那么 我们 在 构造 子类的 时候 会 先 帮助 父类 先构造 。

    class Animal {
        String name ="呜啦啦";
        int age;
    
        public void eat() {
            System.out.println(name + "嗷嗷炫");
        }
    
        public void func() {
            System.out.println("测试 方法 一 ");
        }
    }
    
    class Dog extends Animal {
    
    
        // 狗  能 看 家 特有的 方法
        public void Special() {
            System.out.println(name + "正在看 家");
        }
    
        public void func(int a) {
            System.out.println("测试 方法 二");
        }
    }
    
    class Cat extends Animal {
    
    String name = "小 黑 猫 ";
        // 猫 能 爬树  特有 的 方法
        public void ClimBtree() {
            System.out.println(name + "正在 爬树 ");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Dog dog = new Dog();
        }
    }
    
    • 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


    上面面的代码 ,我们 没有 提供 构造 方法 ,但 编译器 会 默认为 我们 提供 一个 构造 方法 ,如果 这个类 继承了 另外 一个 类 ,编译器 会 默认 在 这个 提供的 默认的 构造方法中 加入 super().

    class Dog extends Animal {
    
    
        // 狗  能 看 家 特有的 方法
        public void Special() {
            System.out.println(name + "正在看 家");
        }
    
        public void func(int a) {
            System.out.println("测试 方法 二");
        }
        public Dog(){
            super();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15


    这里 就 将 编译器 默认 提供的 写 了 出来 ,

    再来 看 一种 情况 :

    在这里插入图片描述


    我们 给 Animal提供 了 一个 带有 两个 参数的 构造 方法,

    此时 我们 的 Dog 类 默认 提供 的 不带 参数 的super() 就失效了 ,这里我们就需要 自己 提供 一个 super() 注意 :这个 super 需要带 两个 参数,而且 得 与 父类构造方法的 参数相同。

    在这里插入图片描述


    这样 就 不会报错 了 。

    我们实例 化 对象 ,也能 验证 是 先 帮 父类 然后 在 帮 自己 。

    class Animal {
        public String name;
        public int age;
    
        // Animal 的 构造 方法
        public Animal(String name,int age) {
            System.out.println("构造方法 测试 二 ");
        }
    
    
    }
    
    class Dog extends Animal {
    
        public void fun() {
            System.out.println("hhh");
        }
        public Dog(){
            super("小黑",29);
            System.out.println("构造方法测试 一 ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    总结:

    在子类构造方法中,并没有写任何关于基类(父类 )构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,

    因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有
    父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

    注意:

    1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法

    1. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。

    2. 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。

    3. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

    在这里插入图片描述

    3.super 的 第三种 用法 调用 父类的普通 方法

    注意 : super 是 不能 在 静态 方法中 使用 的 。

    在这里插入图片描述

    另外 : super() 必须 在第一行(子类帮 父类 构造)

    在这里插入图片描述

    学习 完 super 我们 就来 对比 一下 this

    super : 是 对 父类 对象的 引用 ,

    this : 是 对 当前类 对象的 引用 (调用 当前 对象的 字段 / 属性/ 成员 变量 )

    super 有 三种 方法

    1.super.data 调用 父类的普通成员变量

    2.super.func() 调用 父类 的 普通 方法

    3.super() 调用 父类的 构造方法

    this 的 三种 用法

    1.this.data 调用 当前 对象的 成员变量。

    2.this.func() 调用 当前 对象的 方法 、

    3.this() 调用 当前 对象的 构造 方法

    相同点 :

    1. super() 和 this() 都 只能 在 构造方法的 第一行 。
    2. this 和 super 都不能在 静态方法 中 使用 。
    3. 都是Java中的关键字


    不同点:

    1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成
      员的引用

    2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性

    3. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现

    4. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

    这里 还有 一张图 可以参考 :

    img

    静态代码 块实例代码块小坑


    思考 一下 下面 打印 的 顺序 是 ?

    class Animal{
        public String name;
        public int age;
    
        static {
            System.out.println("Animal 中的 静态 代码 块");
        }
    
        {
            System.out.println("Animal 中的 实例 代码 块");
        }
        
    
    
    }
    class Dog extends Animal{
    
        static{
            System.out.println("Dog 中 的静态 代码 块");
        }
    
        {
            System.out.println("Dog 中 的 实例 代码 块");
        }
        public void func(){
            System.out.println("方法  func");
        }
        
    }
    public class Main {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.func();
        }
    }
    
    • 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

    A: Animal 静态 + Dog 静态 + Animal 实例 +Animal 构造块 + Dog 实例+ Dog 构造块 + func方法

    B: Animal 静态 + Animal 实例 + Animal 构造块 + Dog 静态 + Dog 实例 + Dog 构造块 + func 方法

    c: 其他

    公布答案 :

    在这里插入图片描述


    这里我们就能 得出 结论 :

    1、父类静态代码块优先于子类静态代码块执行,且是最早执行

    2、父类实例代码块和父类构造方法紧接着执行

    3、子类的实例代码块和子类构造方法紧接着再执行

    4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

    在这里插入图片描述

    下面 来 一题 巩固 一下:

    class X{
    	Y y=new Y();//1
    	public X(){//2
    		System.out.print("X");
    	}
    }
    class Y{
    	public Y(){//3
    		System.out.print("Y");
    	}
    }
    public class Z extends X{
    	Y y=new Y();//4
    	public Z(){//5
    		System.out.print("Z");
    	}
    	public static void main(String[] args) {
    		new Z();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20


    A.ZYXX B.ZYXY C.YXYZ D.XYZX

    看到 这一题 :大家 有没有 非常蒙 ? 这 哪有 静态 代码块 ,实例 代码块 , 我 只看到 了 构造 块 。

    上面我们不是 总结 了 : 先执行 父类 静态 ,在 执行 子类 静态, 然后 父类 实例 , 父类 构造方法, 子类 实例 子类 构造 。

    new Z() , Z 继承 了 父类 X 那么 会先 执行 Y y = new Y() , 这是 一个 实例 ,此时 会调用 Y的 构造 方法 , 打印 Y , 然后 执行 X 的 构造 方法,打印 出 X

    下面 就会执行 子类的 实例 Y y = new Y() 然后 打印 出 Y , 最后 执行 Z 的 构造方法 打印 了 Z 。

    最终 答案 : Y X Y Z

    注意: 实例 :包含 实例代码 块 也 包括 实例 对象 。

    这里 我们 虽然 没有出现 静态代码 块 ,实例 代码块 ,但我们通过 new 也得到 了 实例 对象 。 这里 同样需要 先 输出。

    继承 大部分 知识点 学完 我们 来 学习下我们的 访问权限 : protected

    protected 关键字


    这里 再次 请 出我们的 老朋友 :

    在这里插入图片描述


    为什么 有 protected 关键字 :

    1.public 修饰 不管在 那 只要 实例化 了 对象 都能 引用 ,不安全 ,不能实现我们的封装

    2.private 修饰 ,在 子类 不能 使用 ,又过于 安全 (只能 在 同一个 包的 同一类中 使用)。

    为了 两全其美 我们 就 设计 出了 protected

    对 于 类 的 子类(包含了 不同 包 和 同一个 包 ) 和 同一个包的 其他 类 来说 ,protected 修饰的字段和 方法是 可以 访问 的 。

    下面就来演示 一下 :

    1.同一个 包 中 的 同一个 类

    在这里插入图片描述

    2.同一个 包的 不同类

    在这里插入图片描述

    3.不同包的 子类

    在这里插入图片描述

    4.不同包的非子类

    在这里插入图片描述

    总结 :

    public 修饰的 字段或 方法: 不管 是否 在 同一个包底下,是否是 同一个类,都是能够 访问的。

    protected 修饰的 字段 或方法 : 只要是 继承的 子类 ,都能够 访问 被 protected 修饰的 字段 或 方法。

    default (包访问权限) : 只有 在同一个包地下的 变量或 方法,才能 使用 。

    private 修饰的 字段 或 方法: 只用 在本内 中 使用, 权限最小 最安全。

    他们 之间的 权限大小 为 private < default protected < public

    有没有想过 如果 我们 不想要 一个 类 被 继承 ,需要这么 做 。

    这里 java 就提供 了 关键字 final 下面 就来 学习一下。

    final 关键字

    之前我们 也 见过 final 这个 关键字 : 之前我们 说 final 修饰 的 变量是 常量 后续不能 修改 , 这里 我们的 final 的 作用 就是 修饰 类 ,表示 此时 类 是不能 被 继承的。

    在这里插入图片描述

    继承 与 组合

    在这里插入图片描述

    这里 就是 一种 组合 , 组合 同样能够 达到对 代码的 复用效果

    这里 可以 认为 继承 是 is - a 的 关系

    如: 猫 是 一种 动物 , 狗 是 一 种 动物,

    而 组合 : 可以 认为 has - a 的关系

    如: 动物 包含 猫 , 动物包含 狗 。

    想要 了解 更多 可以看 下面这篇文章

    深入理解Java中的组合和继承

    本文 完 : 下文 预告 多态 。

  • 相关阅读:
    贪心算法(一) | leecode刷题笔记
    电源硬件设计----升压(Boost)变换器基础
    获取、设置注释的值
    探讨:UDP广播还有前途吗?(代码验证)
    Qt在工控行业的一些重点知识点
    JAVA中线程池的定义及使用
    Gin中的Cookie和Session的用法
    信创JAVAWEB的相关记录
    html基本标签
    UE4 源码解析----引擎初始化流程
  • 原文地址:https://blog.csdn.net/mu_tong_/article/details/126228878