01_继承的语法与限制(单继承)

一、继承的基本概念

继承是 Java 面向对象编程的三大特性之一(封装、继承、多态),它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码复用和功能扩展。

  • 父类(超类 / 基类):被继承的类,通常包含多个子类的共性属性和方法(如 “动物” 类)。
  • 子类(派生类):继承父类的类,可拥有父类的成员,并能添加自己的特有属性和方法(如 “狗” 类继承 “动物” 类)。

核心作用

  • 代码复用:避免重复编写相同的属性和方法。
  • 功能扩展:子类在父类基础上添加新功能,符合 “开闭原则”(对扩展开放,对修改关闭)。

在这里插入图片描述

二、继承的语法规则

2.1 基本语法

Java 中通过extends关键字实现继承,语法如下:

[修饰符] class 子类名 extends 父类名 {
    // 子类的属性和方法(可新增或重写父类方法)
}
  • extends:意为 “扩展”,表示子类是对父类的扩展。
  • 子类会自动拥有父类中非私有(public、protected、默认权限)的属性和方法。

实例

// 父类:动物
class Animal {
    protected String name; // 受保护的属性(子类可访问)
    
    public void eat() { // 公共方法(子类可继承)
        System.out.println(name + "在吃东西");
    }
}

// 子类:狗(继承动物)
class Dog extends Animal {
    // 新增子类特有方法
    public void bark() {
        System.out.println(name + "在叫");
    }
}

// 使用子类
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "旺财"; // 继承父类的name属性
        dog.eat(); // 调用继承的eat()方法 → 输出“旺财在吃东西”
        dog.bark(); // 调用子类特有方法 → 输出“旺财在叫”
    }
}

2.2 继承的成员访问规则

子类对父类成员的访问需遵循以下规则:

  1. 继承父类非私有成员
    • 父类的public、protected、默认权限(同包)成员会被子类继承。
    • 父类的private成员(私有属性 / 方法)不会被继承(子类无法直接访问,需通过父类的公共方法间接访问)。
  • 示例
class Parent {
    private int id; // 私有属性(子类不继承)
    public String name; // 公共属性(子类继承)
    
    private void showId() { // 私有方法(子类不继承)
        System.out.println(id);
    }
    
    public void showName() { // 公共方法(子类继承)
        System.out.println(name);
    }
}

class Child extends Parent {
    public void test() {
        name = "小明"; // 合法:访问继承的public属性
        showName(); // 合法:调用继承的public方法
        
        // id = 100; // 错误:无法访问父类的private属性
        // showId(); // 错误:无法访问父类的private方法
    }
}
  1. 子类可新增成员:子类可定义自己的属性和方法,实现功能扩展(如上述Dog类的bark()方法)。

三、单继承原则

3.1 单继承的定义

Java 规定,一个类只能直接继承一个父类,即 “单继承”(extends后只能跟一个父类名)。这是 Java 与其他语言(如 C++ 支持多继承)的重要区别。
示例(正确)

// 正确:子类Cat直接继承一个父类Animal
class Cat extends Animal {
    // 子类内容
}

示例(错误)

class A {}
class B {}

// 错误:Java不支持多继承,不能同时继承A和B
class C extends A, B { 
    // 编译错误
}

3.2 单继承的原因

Java 限制单继承,主要是为了避免 “多继承冲突”:

  • 若两个父类有同名方法,子类无法确定继承哪个方法的实现(歧义问题)。
  • 单继承使类的层次关系更清晰,降低代码复杂度和维护成本。

3.3 间接继承(多层继承)

虽然 Java 不支持多继承,但允许多层继承(子类继承父类,父类再继承其他类),形成 “继承链”。

示例

// 顶层父类:生物
class Creature {
    public void breathe() {
        System.out.println("呼吸");
    }
}

// 父类:动物(继承生物)
class Animal extends Creature {
    public void eat() {
        System.out.println("吃东西");
    }
}

// 子类:狗(继承动物,间接继承生物)
class Dog extends Animal {
    public void bark() {
        System.out.println("汪汪叫");
    }
}

// 测试:Dog类拥有所有祖先类的非私有成员
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.breathe(); // 继承自Creature → 输出“呼吸”
        dog.eat(); // 继承自Animal → 输出“吃东西”
        dog.bark(); // 子类特有 → 输出“汪汪叫”
    }
}
  • 多层继承的层次不宜过深(建议不超过 3-4 层),否则会导致代码耦合度高,可读性下降。

四、继承的限制

除单继承外,Java 继承还有以下重要限制:

4.1 构造器不能被继承

父类的构造器不会被子类继承,但子类构造器会默认调用父类的无参构造器(通过super()实现,详见super关键字相关内容)。

示例

class Parent {
    // 父类构造器
    public Parent() {
        System.out.println("父类构造器被调用");
    }
}

class Child extends Parent {
    // 子类构造器
    public Child() {
        // 编译器会自动添加super(),调用父类无参构造器
        System.out.println("子类构造器被调用");
    }
}

// 测试
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        // 输出:
        // 父类构造器被调用
        // 子类构造器被调用
    }
}

4.2 final类不能被继承

被final关键字修饰的类是 “最终类”,不能有子类(无法被继承),通常用于保护核心类不被修改(如java.lang.String、java.lang.Math)。

示例

// final类:不能被继承
final class FinalClass {
    // 类内容
}

// 错误:FinalClass是final类,不能被继承
class SubClass extends FinalClass { 
    // 编译错误
}

4.3 私有成员无法直接访问

父类的private成员(属性、方法)不会被子类继承,子类无法直接访问,需通过父类的public或protected方法间接访问。

示例

class Parent {
    private int age; // 私有属性(子类不可直接访问)
    
    // 父类提供公共方法访问私有属性
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

class Child extends Parent {
    public void test() {
        // age = 20; // 错误:无法直接访问父类的private属性
        setAge(20); // 正确:通过父类的public方法间接访问
        System.out.println(getAge()); // 正确:输出20
    }
}

五、继承的最佳实践

  1. 符合 “is-a” 关系:子类与父类应满足 “子类是父类的一种” 的逻辑(如 “狗是一种动物”),避免不合理继承(如 “学生继承书” 是错误的)。
  2. 控制继承深度:多层继承的层次不宜过深(建议≤3 层),否则会导致类的关系复杂,难以维护。
  3. 优先组合而非继承:若仅需复用其他类的功能,而非 “is-a” 关系,建议使用 “组合”(在类中定义其他类的对象)替代继承,降低耦合度。

示例(组合替代继承)

// 工具类:无需被继承,通过组合使用
class Tool {
    public void doSomething() { ... }
}

// 不继承Tool,而是组合它
class MyClass {
    private Tool tool = new Tool(); // 组合Tool对象
    
    public void useTool() {
        tool.doSomething(); // 复用Tool的功能
    }
}
  1. 父类设计为抽象类或接口:若父类仅作为子类的模板,无实际实例意义,可定义为抽象类(如Animal),强制子类实现抽象方法,规范继承体系。

六、总结

继承是 Java 实现代码复用和扩展的核心机制,其核心要点包括:

  • 语法:通过extends关键字实现,子类继承父类的非私有成员。
  • 单继承:一个类只能直接继承一个父类,避免多继承冲突,但支持多层继承。
  • 限制:私有成员不可直接访问、final类不能被继承、构造器不能被继承。

合理使用继承能显著提高代码复用性,但需遵循 “is-a” 关系和单继承原则,避免过度继承导致的代码复杂性。在不适合继承的场景中,应优先考虑组合等替代方案。

posted @ 2025-07-07 08:21  HuCiZhi  阅读(64)  评论(0)    收藏  举报