子类与继承

基本概念

  • 继承:面向对象编程的重要特性,允许一个类(子类)继承另一个类(父类)的属性和方法。
  • 子类 (Subclass/Derived class):通过 extends 关键字继承父类的类。
  • 父类 (Superclass/Base class):被子类继承的类。

子类的定义

  • 使用 extends 关键字:
    public class 子类名 extends 父类名 {
        // 子类特有的属性和方法
    }
  • Java 中单继承:一个子类只能有一个直接父类,但可以通过链式继承形成继承层次。
  • 所有类默认继承自 Object类(如果未显式指定父类)。

继承的特性

  • 子类继承父类的所有非私有成员(属性、方法),但受访问控制修饰符影响。
  • 不能继承的成员
    • private 修饰的属性和方法(但可以通过 getter/setter 间接访问)。
    • 构造方法(不能继承,但子类可以调用父类构造方法)。
    • 静态方法(不属于实例,但可以通过子类名调用)。
  • 子类可以添加新的属性和方法,也可以重写(Override) 父类的方法。

方法重写 (Override)

  • 子类重新定义父类中已有的方法,实现不同的行为。
  • 重写规则:
    • 方法名、参数列表必须相同。
    • 返回类型需相同或为父类返回类型的子类型(协变返回类型)。
    • 访问权限不能更严格(例如,父类 protected,子类不能改为 private)。
    • 不能抛出更宽泛的异常(可以抛出更具体的异常或不抛出)。
  • 使用 @Override 注解显式标明重写,帮助编译器检查错误。

示例

class Animal {
    public void sound() {
        System.out.println("Animal makes sound");
    }
}
 
class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Meow");
    }
}

super 关键字

  • super:引用父类的对象。
  • 常见用途:
    • 访问父类的属性:super.属性名
    • 调用父类的方法:super.方法名()
    • 调用父类的构造方法:super(参数列表)(必须在子类构造方法的第一行)
  • 如果子类构造方法中未显式调用父类构造方法,编译器会自动插入 super() 调用父类的无参构造方法。如果父类没有无参构造方法,子类构造方法必须显式调用父类的有参构造方法。
  • 拓展:不使用super调用父类方法,方法链:创建无名对象直接调用new 类名.方法名

构造方法在继承中的行为

  • 子类构造方法会隐式或显式调用父类构造方法。
  • 执行顺序:
    1. 调用父类构造方法(初始化父类部分)。
    2. 初始化子类的实例变量。
    3. 执行子类构造方法中的代码。

抽象类与抽象方法

抽象类用于提炼父类模板,抽象方法把不确定行为留给子类实现。详细见:抽象类

接口与实现

  • 接口(interface)是一种更抽象的“继承”形式(通过 implements 实现)。
  • 一个类可以实现多个接口(弥补 Java 单继承的限制)。
  • 接口中的方法默认是 public abstract,属性默认是 public static final。 详细见:接口与实现

多态 (Polymorphism)

  • 向上转型:子类对象赋值给父类引用(例如 Animal a = new Cat();)。
  • 通过父类引用调用方法时,实际执行的是子类重写的方法(动态绑定)。
  • 编译时类型决定可调用的成员,运行时类型决定实际行为。

详细见:多态

最佳实践

  • 优先使用组合而非继承:组合(HAS-A)比继承(IS-A)更灵活,降低耦合。
  • 继承用于 “is-a” 关系,如 Dog is an Animal
  • 避免过度继承层级过深,建议不超过 3-4 层。
  • 如果父类方法不确定子类是否需要重写,可考虑使用 abstract 方法或设为默认空实现。

instanceof运算符

用来检查对象是否是特定类或其父类的实例。语法为 对象 instanceof 类名,返回布尔值。在继承中常用于多态场景的类型判断,例如:

Animal animal = new Cat();  
if (animal instanceof Cat) {  
    System.out.println("这是一只猫");  
}  

注意:若对象为null,instanceof会直接返回false。

final关键字

final 可以限制类被继承、方法被重写、变量被重新赋值。详细见:final关键字

上转型变量

  • 上转型变量:子类对象赋值给父类引用。
  • 使用 System.out.println(上转型变量) 时,实际调用的是对象的 toString() 方法,体现动态绑定(多态)。
  • 具体输出取决于对象实际类型所属类是否重写了 toString()
    • 若已重写:输出子类自定义的字符串。
    • 若未重写:默认输出 类名@哈希码(继承自 Object类)。
  • 本质:编译时引用类型决定可调用的方法,运行时对象类型决定实际执行的方法。
  • 可访问部分
  • 唯有父类变量、方法以及子类重写的方法

abstract类和abstract()方法

抽象类的理解:抽象出重要的行为标准,减少在细节上浪费的时间,从而设计出易维护、易拓展的程序。详细见:抽象类

开-闭原则

定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。 核心思想**:通过抽象和继承实现功能扩展,而不用修改原有代码。 典型实现方式

  • 使用抽象类/接口定义稳定部分
  • 通过子类/实现类进行扩展

面对对象的程序与设计(基础入门) 类与对象 封装 抽象类 多态 接口与实现 接口回调与上转型运用