4.1 继承

思维导图:
4.1 继承_第1张图片

 4.1 继承_第2张图片

第4章 面向对象(下)


学习目标:

  • 了解面向对象中的继承特性,掌握继承的概念与特点。
  • 掌握方法的重写,能够在子类中重写父类方法。
  • 掌握super关键字,明白如何在类中使用super访问父类成员。
  • 理解final关键字的作用,知道如何使用final修饰类、方法和变量。
  • 熟悉抽象类的定义与使用。
  • 理解接口的定义,能独立编写接口。
  • 掌握多态性,知道如何利用对象类型转换解决继承中的多态问题。
  • 了解Object类及其常用方法。
  • 熟悉内部类及其四种形式的特点。

继续学习: 第3章已经介绍了面向对象的基础用法以及封装性。本章将进一步深入探讨继承和多态。

4.1 继承

4.1.1 继承的概念
  • 现实与编程的对应:

    • 现实中的继承:子女继承父辈的财产、事业等。
    • 编程中的继承:描述事物间的从属关系。例如,猫和狗都是动物,可以说猫和狗继承自动物类。
  • 示例:

    • 动物(Animal)
      • 猫(Cat)
        • 波斯猫(PersianCat)
        • 巴厘猫(BalineseCat)
      • 狗(Dog)
        • 沙皮狗(SharPeiDog)
        • 斑点狗(DalmatianDog)
  • Java中的继承:

    • 子类自动继承父类的属性和方法。
    • 使用extends关键字表示继承。
class 父类 {
  // ...
}

class 子类 extends 父类 {
  // ...
}
4.1.2 示例解析

Example01.java文件中:

  • Animal类定义了name, age, 和COLOR属性,以及相应的gettersetter方法。
  • Dog类继承自Animal类,因此可以访问Animal类的属性和方法。
  • main方法中,我们创建了Dog类的对象并设置了其nameage属性的值,然后输出了这些值。

结果表明,尽管子类Dog没有明确定义任何属性和方法,但它能够继承并使用来自父类Animal的属性和方法。


4.1.3 继承的扩展

子类不仅可以继承父类的特性,还可以添加自己的特性。

Example02.java中:

  • 我们对Dog类进行了扩展,添加了一个新的color属性以及相应的gettersetter方法。

这说明,在子类中,我们可以保留父类的特性的同时添加新的特性。


  • 文件4-2的内容

    • Dog类继承:在文件4-2中,Dog类继承了Animal类的属性和方法。
    • 新增属性:Dog类增加了颜色(color)的getter和setter方法。
    • 示例代码:在main()方法中,通过dog对象分别调用Animal和Dog类的setter方法来设置名称、年龄和颜色。接着,调用getter方法来获取这些属性值。
    • 运行结果:输出“名称:牧羊犬,年龄:3,颜色:黑色”。
  • 继承中的权限注意事项

    • 子类可以继承父类的成员和方法。
    • 但子类只能访问使用publicprotected修饰的属性和方法。
    • 使用defaultprivate修饰的属性和方法不能被子类访问。
  • 类继承中的几个关键点

    1. 单继承原则:在Java中,每个类只能直接继承一个父类。例如,一个类不能同时继承A类和B类。
    2. 多类继承同一父类:多个子类可以共同继承同一个父类。例如,B类和C类都可以继承A类。
    3. 多层继承:Java支持多层继承。例如,C类可以继承B类,而B类又继承A类。在这种情况下,C类即是B类的子类,也是A类的子类。
    4. 父类和子类的相对性:在Java中,父类和子类的概念是相对的。一个类可能是另一个类的父类,同时也可能是其他类的子类。

4.1 继承_第3张图片

4.1.2 方法的重写

重写的概念

在面向对象的编程中,当子类继承父类后,会自动继承父类的所有方法。但在某些情境下,子类可能需要对其继承的方法进行修改或调整。这个过程被称为“方法的重写”。

要点:

  • 方法重写也被称为覆盖。
  • 重写的方法和被重写的方法必须有相同的方法名、参数列表和返回值类型。
方法的重写实例

考虑以下代码示例:

// 定义Animal类
class Animal {
    // 定义动物叫的方法
    void shout() {
        System.out.println("动物发出叫声");
    }
}

// 定义Dog类,继承Animal类
class Dog extends Animal {
    // 重写父类Animal的shout()方法
    void shout() {
        System.out.println("汪汪汪……");
    }
}

// 定义测试类
public class Example03 {
    public static void main(String[] args) {
        Dog dog = new Dog();  // 创建Dog类的实例对象
        dog.shout();          // 调用Dog类重写的shout()方法
    }
}

此代码的运行结果为“汪汪汪……”。

注意点
  1. 方法重写的目的是为了让子类具有更具体或与父类不同的行为。
  2. 子类重写父类方法时,不能使用比父类方法更严格的访问权限。例如,如果父类的方法是public,那么子类重写的方法不能是private。

思考与总结

  • 通过方法重写,子类可以继承父类的功能,同时还可以根据自己的需要对这些功能进行改进或扩展。
  • 在Java中,方法的重写是多态的一个关键组成部分,允许程序在运行时动态地选择应该调用哪个方法。
  • 当子类的对象调用一个被重写的方法时,它总是调用子类中的版本,而不是父类中的版本。
提示

当重写一个方法时:

  • 保持方法签名的一致性(即相同的方法名、参数列表和返回类型)。
  • 不要在子类中使用比父类中被重写的方法更严格的访问权限。

4.1 继承_第4张图片

4.1.3 super关键字

介绍

当子类重写父类的方法后,子类对象将无法访问父类中被子类重写过的方法。为了解决这个问题,Java提供了super关键字,使用super关键字可以在子类中访问父类的非私有方法、非私有属性以及构造方法。

使用super关键字访问父类的属性和方法

  1. 格式

    super.属性
    super.方法(参数1, 参数2, ...)
    

  2. 案例:如文件4-5所示,Dog类通过super关键字访问父类Animalshout()方法和name属性。

    // 定义Animal类
    class Animal {
        String name = "牧羊犬";
        
        void shout() {
            System.out.println("动物发出叫声");
        }
    }
    
    // 定义Dog类,继承Animal类
    class Dog extends Animal {
        public void shout() {
            super.shout();
            System.out.println("汪汪汪……");
        }
    
        public void printName() {
            System.out.println("名字:" + super.name);
        }
    }
    
    // 测试类
    public class Example05 {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.shout();
            dog.printName();
        }
    }
    

    运行结果:动物发出叫声,汪汪汪……,名字:牧羊犬

使用super关键字调用父类的构造方法

  1. 格式

    super(参数1, 参数2, ...)
    
  2. 案例:如文件4-6所示,Dog类通过super关键字调用父类Animal的有参构造方法。

    // 定义Animal类
    class Animal {
        private String name;
        private int age;
        
        public Animal(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String info() {
            return "名称:" + this.name + ", 年龄:" + this.age;
        }
    }
    
    // 定义Dog类,继承Animal类
    class Dog extends Animal {
        private String color;
    
        public Dog(String name, int age, String color) {
            super(name, age);
            this.color = color;
        }
    
        @Override
        public String info() {
            return super.info() + ", 颜色:" + this.color;
        }
    }
    
    // 测试类
    public class Example06 {
        public static void main(String[] args) {
            Dog dog = new Dog("牧羊犬", 3, "黑色");
            System.out.println(dog.info());
        }
    }
    

    运行结果:名称:牧羊犬,年龄:3, 颜色:黑色

注意事项

  • 使用super调用父类构造方法的代码必须位于子类构造方法的第一行。
  • 使用thissuper调用构造方法代码都要求必须放在构造方法的首行,所以不能同时出现。

superthis关键字的对比

区别点 super this
访问属性 直接访问父类中的非私有属性 访问本类中的属性,如果本类中没有该属性,则从父类中继续查找
调用方法 直接调用父类中的非私有方法 调用本类中的方法,如果本类中没有该方法,则从父类中继续查找
调用构造方法 调用父类构造方法,必须放在子类构造方法的首行 调用本类构造方法,必须放在构造方法的首行

4.1 继承_第5张图片 4.1 继承_第6张图片

4.1 继承_第7张图片 4.1 继承_第8张图片

4.1 继承_第9张图片 4.1 继承_第10张图片

4.1 继承_第11张图片 总结:

4.1 继承的重点:

  1. 继承的定义:继承是 Java 面向对象的一个核心机制,它允许一个类继承另一个类的属性和方法。
  2. 关键字 extends:在 Java 中,使用 extends 关键字来表示一个类继承另一个类。
  3. 父类和子类:在继承中,被继承的类称为父类或超类,继承父类的类称为子类。
  4. 方法的重写:子类可以重写父类的方法,以提供特定于其自身的实现。
  5. super 关键字:在子类中,super 关键字被用来引用父类的成员(方法、属性)和构造器。

难点:

  1. 方法重写的规则:在重写方法时,必须保持方法签名(方法名称和参数列表)相同,并且子类的方法不能降低父类方法的访问权限。
  2. 使用 super 关键字:理解何时以及如何正确使用 super 关键字来调用父类的构造器或方法可能需要实践。
  3. 构造器和继承:父类的构造器不被子类继承,但子类的构造器必须(显式或隐式)调用父类的构造器。

易错点:

  1. 访问修饰符的误用:尝试访问父类的 private 成员或降低重写方法的访问权限时会导致错误。
  2. 忘记调用父类的构造器:如果父类没有默认的无参数构造器,并且在子类的构造器中没有显式调用父类的构造器,这会导致编译错误。
  3. superthis 的混淆:混淆它们的用途或在同一构造器中同时使用它们(因为它们都需要在构造器的首行)可能导致错误。
  4. 方法隐藏:如果子类中定义了一个与父类中同名但参数不同的方法,这不是重写,而是方法的隐藏,有时可能会导致预期之外的行为。

综上,理解和应用 Java 的继承机制需要时间和实践,但它为创建模块化和可重用的代码提供了强大的工具。

4.1 继承_第12张图片

你可能感兴趣的:(夏驰和徐策从零开始学JAVA,开发语言,java)