Java 学习40:继承

一、继承的基本概念

继承是一种由已有类创建新类的机制。新类(子类、派生类)能继承已有类(父类、基类)的属性和方法,并且可以添加自己独有的属性和方法。在 Java 中,继承通过 extends 关键字来实现。

二、继承的语法

class 父类 {

}

class 子类 extends 父类 {

}

三、继承的示例

java 复制代码
// 父类
class Shape {
    String color;
 
    void setColor(String color) {
        this.color = color;
    }
 
    String getColor() {
        return color;
    }
}
 
// 子类
class Rectangle extends Shape {
    // 不要重复color属性及方法,
    // 只需要定义新增的width和height属性及方法:
    double width;
    double height;
 
    double calculateArea() {
        return width * height;
    }
}

四、继承的特点

**1. 单继承:**Java 只支持单继承,不支持多继承,但支持多层继承。

**2. 传递性:**若类 B 继承自类 A,类 C 继承自类 B,那么类 C 也会继承类 A 的属性和方法。

**3. 默认继承 Object 类:**Java 中所有的类都直接或者间接的继承于 Object 类。如果一个类没有明确继承其他类,那么它会默认继承 Object 类。

五、方法重写

方法重写是指子类重新定义父类中已有的方法。当子类需要修改父类方法的行为时,可以使用方法重写。

(一)方法重写的规则

**1. 方法签名必须一致:**方法名、参数列表和返回类型必须与父类方法完全相同。Java 5 及以上版本允许返回类型可以是父类方法返回类型的子类。

**2. 访问权限不能更严格:**子类方法的访问权限必须与父类一致或更宽松。

**3. 不能抛出更广泛的异常:**子类方法不能抛出比父类方法更广泛的受检异常。

**4. private、final 和 static 方法不能被重写:**private 方法在类内部可见,不能被其他类访问;final 关键字用于防止方法被修改;而 static 方法属于类本身,不能被重写。当在子类中定义一个与父类同名的 static 方法时,实际上是在子类中定义了一个新的静态方法,而不是重写了父类的静态方法。

(二)方法重写的注意事项

建议在重写方法上添加 @Override 注解,编译器会检查方法是否正确重写,避免拼写错误或参数不匹配。

(三)方法重写实例

java 复制代码
class Shape {
    void draw() {
        System.out.println("Drawing a shape");
    }
}
 
class Circle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a circle");
    }
}
 
class Square extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a square");
    }
}
 
public class PolymorphismExample {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Square();
 
        shape1.draw(); // 输出 "Drawing a circle"
        shape2.draw(); // 输出 "Drawing a square"
    }
}

六、构造方法

构造方法用于对象的创建与初始化,方法名与类名相同且无返回类型。

根据 Java 的继承机制,子类的构造方法必须先调用父类的构造方法,再执行自己。这是因为子类需要继承父类的属性,而父类的构造方法负责初始化这些属性。

如果子类没有显式调用父类的构造方法,编译器会自动隐式调用父类的无参构造方法,即 super() 。在这种情况下,父类必须存在无参构造方法,否则编译会报错。

如果父类只定义了有参构造方法,子类必须显式调用父类的有参构造方法,即super(参数)。否则编译会报错。

例1:父类存在无参构造方法

java 复制代码
class Person {
    protected String name;
    protected int age;

    public Person() {        
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        this.score = score; // 先执行super(),再执行这句代码
    }
}

例2:父类只定义了有参构造方法

java 复制代码
class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(name, age); // 父类只定义了有参构造方法,子类必须显式调用父类的有参构造方法
        this.score = score;
    }
}

七、this 和 super 关键字

this 指向当前对象本身;用于访问本类的属性和方法、调用本类其他构造方法;

super 指向当前对象的父类对象;用于访问父类的属性和方法、调用父类构造方法。

java 复制代码
class Animal {
    void eat() {
        System.out.println("吃饭");
    }
}
 
class Dog extends Animal {
    @Override
    void eat() {
        System.out.println("啃骨头");
    }
    void eatTest() {
        super.eat();  // 调用父类方法
        this.eat();   // 调用自己的方法,可以省略this,只写eat()
    }
}

八、继承的优缺点

(一)优点

  1. 实现代码复用,减少代码冗余。

  2. 便于系统的扩展和维护。

  3. 实现多态性,增强程序的灵活性。

(二)缺点

  1. 过度使用继承会导致类之间的耦合度增加,降低代码的可维护性。

  2. 父类的修改可能会对多个子类产生影响。

九、区分继承和组合

在使用继承时,我们要注意逻辑一致性。

比如,Book 类和 Student 类都有 name 属性,那么,我们能不能让 Student 继承自 Book 呢?

显然,从逻辑上讲,这是不合理的。究其原因,是因为 Student 与 Person 是 is 关系,而 Student 与 Book 是 has 关系。

具有 has 关系不应该使用继承,而是使用组合,即 Student 可以持有一个 Book 实例:

class Student extends Person {

protected Book book;

protected int score;

}

继承是 "is-a" 关系(例如,学生是人),而组合是 "has-a" 关系(例如,学生有书)。在设计类时,要优先考虑组合而非继承,这样可以降低类之间的耦合度。

相关推荐
p***q782 小时前
【保姆级教程】apache-tomcat的安装配置教程
java·tomcat·apache
2501_941148612 小时前
C++实时数据处理实战:多线程与异步IO结合高性能代码解析
java·后端·struts
u***u6852 小时前
C++在系统中的异常处理
java·开发语言·c++
空空kkk2 小时前
SpringMVC——拦截器
java·数据库·spring·拦截器
文涛是个小白呀2 小时前
Java集合大调研
java·学习·链表·面试
我也爱吃馄饨2 小时前
写的webpack插件如何适配CommonJs项目和EsModule项目
java·前端·webpack
Seven972 小时前
剑指offer-43、左旋转字符串
java
梵得儿SHI2 小时前
(第七篇)Spring AI 基础入门总结:四层技术栈全景图 + 三大坑根治方案 + RAG 进阶预告
java·人工智能·spring·springai的四大核心能力·向量维度·prompt模板化·向量存储检索
i***27953 小时前
Spring boot 3.3.1 官方文档 中文
java·数据库·spring boot