您的位置:

Java中子类重写父类方法

在Java中,子类可以重写父类中的方法。这是面向对象编程的一个重要特性,它允许子类对父类中继承的方法进行修改或扩展,从而实现更灵活的编程。

1. 什么是方法重写

方法重写(也叫方法覆盖)是指子类中定义与父类中同名、同参数、同返回值类型的方法,从而覆盖(或替换)父类中的方法。当某个方法被子类重写后,调用该方法时,将执行子类中的方法,而不再执行父类中的方法。

使用方法重写,可以让子类继承父类中原有的行为,同时又可以根据子类自身的特性,修改或扩展父类中的方法,使其更符合子类自己的需求。

2. 方法重写的要求

Java中方法重写必须满足以下要求:

  • 方法名必须与父类中被重写的方法名相同;
  • 方法的参数类型、个数、顺序都必须与被重写的方法相同;
  • 返回值类型也必须与被重写的方法相同或者是它的子类;
  • 访问修饰符不能比父类中被重写的方法的访问修饰符更严格。

另外,如果父类中被重写的方法是final或private类型的,则不能被子类重写。

3. 方法重写的示例

下面是一个简单的例子,演示了如何在子类中重写父类中的方法:

class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("猫发出“喵喵”的声音");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.makeSound(); // 输出:猫发出“喵喵”的声音
    }
}

上面的代码中,Animal类是一个父类,定义了一个名为makeSound的方法;而Cat类继承自Animal类,并覆盖了makeSound方法,使其输出“猫发出‘喵喵’的声音”。

在Main类中,我们实例化了一个Cat对象,并将其赋值给一个Animal引用,这样就可以调用该对象的makeSound方法。由于Cat中重写了makeSound方法,所以输出的是“猫发出‘喵喵’的声音”,而不是Animal中的默认实现。

4. 方法重写的注意事项

4.1 被重写的方法不能为final类型

final修饰的方法是不能被子类重写的。如果在子类中尝试去重写一个final方法,编译器会报错:

class Animal {
    public final void makeSound() {}
}

class Cat extends Animal {
    public void makeSound() {} // 编译错误:makeSound() 无法覆盖 Animal.makeSound();被覆盖的方法为 final
}

4.2 方法重写不能改变访问修饰符

方法重写时,访问修饰符不能比父类中被重写的方法的访问修饰符更严格。如果在子类中将父类中被重写的方法声明为private或protected类型,编译器会报错。但是,如果在子类中将父类中的public方法改为protected或private,不会报错,但是也不能通过编译。

class Animal {
    protected void makeSound() {}
}

class Cat extends Animal {
    private void makeSound() {} // 编译错误:makeSound() in Cat cannot override makeSound() in Animal; attempting to assign weaker access privileges; was protected
}

4.3 父类和子类里的方法参数要完全一样

父类和子类中重写的方法必须有相同的参数类型、参数个数和顺序。如果不满足这个条件,编译器会报错:

class Animal {
    public void makeSound(String sound) {}
}

class Cat extends Animal {
    public void makeSound(int sound) {} // 编译错误:makeSound(int) in Cat cannot override makeSound(String) in Animal
}

4.4 父类和子类里的方法返回类型要匹配

父类和子类中重写的方法的返回类型必须相同,或者子类的返回类型必须是父类的返回类型的子类:

class Animal {
    public Number makeSound() {return 0;}
}

class Cat extends Animal {
    public Integer makeSound() {return 0;} // 编译错误:makeSound() in Cat cannot override makeSound() in Animal; return type Integer is not compatible with Number
}

上面的代码中,Animal类中makeSound方法的返回类型是Number,而Cat类中重写的makeSound方法的返回类型是Integer。这是不合法的,因为Integer虽然是Number的子类,但并不等价于Number。

4.5 方法重写时要保证语义一致

在重写父类的方法时,应该保证子类中的方法语义和父类中方法的语义一致。也就是说,重写的方法不能改变原来方法的含义,否则容易出现程序错误。

例如:

class Animal {
    public void makeSound(int volume) {}
}

class Cat extends Animal {
    public void makeSound(int volume, String soundType) {} // 这种覆盖是不一致的,编译错误
}

上面的代码中,Cat类中重写makeSound方法时,添加了一个新的参数soundType,这会导致Cat类的makeSound方法和Animal类的makeSound方法语义不一致。所以编译时会报错。

5. 总结

Java中,方法重写是子类继承父类时的一种特性。它允许子类重写父类中的方法,从而修改或扩展父类中原有的行为。但是,在编写重写方法时需要注意许多细节,包括方法名、访问修饰符、参数类型和顺序、返回类型等。只有遵守这些规则,才能实现正确的方法重写。