【JAVA】Java基础—面向对象编程:继承—重写父类方法

在Java开发中,重写(Override)是面向对象编程(OOP)中的一个重要概念。它允许子类提供父类方法的具体实现,从而改变或扩展父类的行为。重写是实现多态性的重要手段,使得程序在运行时能够根据对象的实际类型来调用相应的方法。

在实际应用中,重写父类方法的场景非常广泛。例如,假设我们正在开发一个图形处理软件,其中有多种形状(如圆形、矩形、三角形等)。我们可以定义一个父类Shape,然后为每种形状创建子类。在这些子类中,我们可以重写Shape类中的draw方法,以实现不同形状的绘制逻辑。

1. 什么是重写?

重写是指在子类中重新定义父类的方法。重写的方法必须与父类的方法具有相同的方法名、参数列表和返回类型。重写的目的是为了提供子类特有的实现。

2. 重写的规则

  • 方法名相同:子类方法的名称必须与父类方法相同。

  • 参数列表相同:子类方法的参数列表必须与父类方法的参数列表相同。

  • 返回类型相同:子类方法的返回类型必须与父类方法的返回类型相同,或者是其子类(协变返回类型)。

  • 访问修饰符:子类方法的访问修饰符不能比父类方法的修饰符更严格。例如,如果父类方法是public,那么子类方法不能是protectedprivate

  • 抛出异常:子类方法可以抛出父类方法抛出的异常,也可以抛出更具体的异常,但不能抛出更广泛的异常。

示例代码

下面我们通过一个简单的示例来演示如何重写父类方法。

示例 1:基本的重写
// 定义一个父类 Shape
class Shape {
    // 父类方法
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

// 定义一个子类 Circle 继承自 Shape
class Circle extends Shape {
    // 重写父类的 draw 方法
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

// 定义一个子类 Rectangle 继承自 Shape
class Rectangle extends Shape {
    // 重写父类的 draw 方法
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        // 创建 Shape 类型的引用指向 Circle 对象
        Shape shape1 = new Circle();
        shape1.draw(); // 输出: Drawing a circle

        // 创建 Shape 类型的引用指向 Rectangle 对象
        Shape shape2 = new Rectangle();
        shape2.draw(); // 输出: Drawing a rectangle
    }
}
代码解释
  1. **父类 Shape**:定义了一个draw方法,表示绘制形状。

  2. 子类 Circle 和 **Rectangle**:分别重写了draw方法,提供了各自的实现。

  3. **主类 Main**:创建了Shape类型的引用,但指向不同的子类对象。通过这种方式,我们实现了多态性。

示例 2:重写与多态

在实际开发中,重写通常与多态结合使用。我们可以使用父类类型的引用来调用子类的方法,具体调用哪个方法在运行时决定。

// 父类
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

// 子类 Dog
class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

// 子类 Cat
class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Cat meows");
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.sound(); // 输出: Dog barks
        myCat.sound(); // 输出: Cat meows
    }
}
代码解释
  1. **父类 Animal**:定义了一个sound方法,表示动物发出的声音。

  2. 子类 Dog 和 **Cat**:分别重写了sound方法,提供了不同的实现。

  3. **主类 Main**:通过Animal类型的引用调用DogCatsound方法,展示了多态性。

示例 3:重写中的访问修饰符

重写方法时,访问修饰符的选择也很重要。以下示例展示了如何在重写时使用不同的访问修饰符。

// 父类
class Vehicle {
    // 父类方法,使用 public 修饰符
    public void start() {
        System.out.println("Vehicle is starting");
    }
}

// 子类 Car
class Car extends Vehicle {
    // 重写父类方法,仍然使用 public 修饰符
    @Override
    public void start() {
        System.out.println("Car is starting");
    }
}

// 子类 Bike
class Bike extends Vehicle {
    // 重写父类方法,使用 protected 修饰符(错误示例)
    // @Override
    // protected void start() { // 这将导致编译错误
    //     System.out.println("Bike is starting");
    // }
}

// 主类
public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // 输出: Car is starting
    }
}
代码解释
  1. **父类 Vehicle**:定义了一个start方法,使用public修饰符。

  2. **子类 Car**:重写了start方法,仍然使用public修饰符。

  3. **子类 Bike**:尝试使用protected修饰符重写start方法,这会导致编译错误,因为protectedpublic更严格。

生活中的比喻

重写可以用生活中的许多场景来比喻。例如,想象一个父亲和他的孩子。父亲有一个技能,比如“游泳”。孩子可以继承这个技能,但他可以选择在游泳的方式上做出改变,比如“花样游泳”或“潜水”。在这个比喻中,父亲的游泳方式相当于父类的方法,而孩子的游泳方式则是重写的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值