当前位置: 首页 > news >正文

六、面向对象编程(2)

继承是面向对象编程的三大特性之一(封装、继承、多态),它允许我们基于现有类创建新类,实现代码复用和层次化设计。本文将从六个核心方面系统解析Java继承机制。


一、继承快速入门

1.1 基本语法

class ParentClass {
    // 父类成员
}

class ChildClass extends ParentClass {
    // 子类特有成员
}

1.2 入门示例

class Animal {
    void eat() {
        System.out.println("Eating...");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Barking...");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.eat();  // 继承自Animal
        myDog.bark(); // 自有方法
    }
}

二、继承的优势

  1. 代码复用:子类自动获得父类非私有成员
  2. 扩展性:在不修改父类的情况下扩展功能
  3. 多态基础:为方法重写和方法重载提供支持
  4. 层次结构:更符合现实世界的分类逻辑

三、权限修饰符详解

修饰符

类内部

同包

不同包子类

不同包非子类

private

默认(包)

protected

public

继承规则:

  • 子类继承父类的publicprotected成员
  • 默认访问权限成员只能在同包继承
  • private成员不可继承但可通过公有方法访问

典型继承场景:

class Parent {
    private String secret;      // 仅本类可见
    String familyName;          // 同包可见
    protected String heirloom;  // 子类可见
    public String motto;        // 全局可见
}

class Child extends Parent {
    void showInherited() {
        // System.out.println(secret);     // 编译错误
        System.out.println(familyName);   // 同包可访问
        System.out.println(heirloom);     // 子类可访问
        System.out.println(motto);        // 始终可访问
    }
}

四、方法重写(Override)

4.1 概念

当子类觉得父类方法不好用,或者无法满足父类需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。

注意:重写后,方法的访问遵循就近原则

4.2 核心规则

1.重写的方法上面,可以加一个注解@Override,用于标注这个方法是复写的父类方法

2.子类复写父类方法时,访问权限必须大于或者等于父类方法的权限

public > protected > 缺省

3. 重写的方法返回值类型,必须与被重写的方法返回值类型一样,或者范围更小

4. 私有方法、静态方法不能被重写,如果重写会报错。

4.3 示例代码

  • 写一个A类作为父类,定义两个方法print1和print2
public class A {
    public void print1(){
        System.out.println("111");
    }

    public void print2(int a, int b){
        System.out.println("111111");
    }
}
  • 再写一个B类作为A类的子类,重写print1和print2方法。
public class B extends A{
    // 方法重写
    @Override // 安全,可读性好
    public void print1(){
        System.out.println("666");
    }


    // 方法重写
    @Override
    public void print2(int a, int b){
        System.out.println("666666");
    }
}

接下来,在测试类中创建B类对象,调用方法

public class Test {
    public static void main(String[] args) {
        // 目标:认识方法重写,掌握方法重写的常见应用场景。
        B b =  new B();
        b.print1();
        b.print2(2, 3);
    }
}

执行代码,我们发现真正执行的是B类中的print1和print2方法


五、子类成员访问特点

5.1 访问优先级

  1. 子类成员变量 > 父类成员变量
  2. 原则:在子类中访问其他成员(成员变量、成员方法),是依据就近原则的

定义一个父类,代码如下

public class F {
    String name = "父类名字";

    public void print1(){
        System.out.println("==父类的print1方法执行==");
    }
}

再定义一个子类,代码如下。有一个同名的name成员变量,有一个同名的print1成员方法;

public class Z extends F {
    String name = "子类名称";
    public void showName(){
        String name = "局部名称";
        System.out.println(name); // 局部名称
    }

    @Override
    public void print1(){
        System.out.println("==子类的print1方法执行了=");
    }

    public void showMethod(){
        print1(); // 子类的
    }
}

接下来写一个测试类,观察运行结果,我们发现都是调用的子类变量、子类方法。

public class Test {
    public static void main(String[] args) {
        // 目标:掌握子类中访问其他成员的特点:就近原则。
        Z z = new Z();
        z.showName();
        z.showMethod();
    }
}
  • 如果子类和父类出现同名变量或者方法,优先使用子类的;此时如果一定要在子类中使用父类的成员,可以加this或者super进行区分。
public class Z extends F {
    String name = "子类名称";

    public void showName(){
        String name = "局部名称";
        System.out.println(name); // 局部名称
        System.out.println(this.name); // 子类成员变量
        System.out.println(super.name); // 父类的成员变量
    }

    @Override
    public void print1(){
        System.out.println("==子类的print1方法执行了=");
    }

    public void showMethod(){
        print1(); // 子类的
        super.print1(); // 父类的
    }
}

六、构造器访问特点

6.1 构造器调用规则

  1. 子类构造器必须调用父类构造器
  2. 默认调用父类无参构造器super()
  3. 显式调用必须放在构造器首行

6.2 示例分析

class Person {
    private String name;
    
    public Person(String name) {
        this.name  = name;
        System.out.println("Person 构造器执行");
    }
}

class Student extends Person {
    private int grade;
    
    public Student(String name, int grade) {
        super(name);  // 必须首行调用
        this.grade  = grade;
        System.out.println("Student 构造器执行");
    }
}

// 测试输出:
Student s = new Student("Alice", 10);
// 输出顺序:
// Person构造器执行
// Student构造器执行

最佳实践与注意事项

  1. 遵循is-a关系进行继承设计
  2. 谨慎使用继承层级(建议不超过3层)
  3. 优先使用组合替代深层继承
  4. 注意构造器调用链的执行顺序
  5. 使用@Override注解增强代码可读性

相关文章:

  • 多模态基础模型训练笔记-第一篇InternVL-g
  • HTTP 与 HTTPS:协议详解与对比
  • 蓝桥杯 Java B 组之简单动态规划(爬楼梯、斐波那契数列)
  • 本地通过隧道连接服务器的mysql
  • 1-10 github注册仓库
  • MySQL Workbench 8.0不支持非SSL连接
  • 喜报!博睿数据案例获经观传媒“2024年度数字转型创新案例”!
  • 信息量与信息熵
  • 计算机性能与网络体系结构探讨 —— 基于《计算机网络》谢希仁第八版
  • VMware vSphere数据中心虚拟化——搭建vCenter Server7.0数据中心集群
  • 大语言模型推理中的显存优化 有哪些
  • 可编程超表面任意旋转偏振方向并以线性和非线性方式操控相位
  • cpu、gpu查看
  • Ollama 安装命令
  • [C++]多态详解
  • DeepSeek 通过 API 对接第三方客户端 告别“服务器繁忙”
  • C++演示中介模式
  • 【设计模式】03-理解常见设计模式-行为型模式(专栏完结)
  • SpringBoot多数据源实践:基于场景的构建、实现和事务一体化研究
  • 第1825天 | 我的创作纪念日:缘起、成长经历、大方向
  • 首映|《星际宝贝史迪奇》真人电影,不变的“欧哈纳”
  • 张巍任中共河南省委副书记
  • 本周看啥|《歌手》今晚全开麦直播,谁能斩获第一名?
  • 中国首艘海洋级智能科考船“同济”号试航成功,可搭载水下遥控机器人
  • 泽连斯基与埃尔多安会面,称已决定派遣代表团前往伊斯坦布尔
  • 最高法、证监会:常态化开展证券纠纷代表人诉讼,降低投资者维权成本