在本教程中,我们将借助示例来学习Java中的方法重写。
在上一教程中,我们了解了继承。继承是一个OOP属性,它使我们可以从现有的类(父类)派生一个新的类(子类),而子类继承超类的属性和方法。
现在,如果在父类和子类中都定义了相同的方法,则子类的方法将覆盖超类的方法。这称为方法覆盖(方法重写)。
class Animal { public void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { @Override public void displayInfo() { System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
输出:
I am a dog.
在以上程序中,displayInfo()方法同时存在于Animal父类和Dog子类中。
当我们使用d1对象(子类的对象)调用displayInfo()时,会调用子类Dog中的方法。子类的displayInfo()方法覆盖父类的相同方法。
注意在我们的示例中使用了@Override注释。在Java中,注释是我们用来向编译器提供信息的元数据。这里,@Override注释告诉编译器,该注释之后的方法将覆盖超类的方法。
使用@Override不是强制性的。但是,当我们使用这个方法时,该方法应该遵循覆盖的所有规则。否则,编译器将生成错误。
父类和子类都必须具有相同的方法名称,相同的返回类型和相同的参数列表。
我们不能重写声明为final和static的方法。
我们应该始终重写超类的抽象方法(将在以后的教程中进行讨论)。
在Java中执行重写时出现的一个常见问题是:
我们可以在重写后访问超类的方法吗?
答案是肯定的。要从子类访问超类的方法,我们使用super关键字。
class Animal { public void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { public void displayInfo() { super.displayInfo(); System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
输出:
I am an animal. I am a dog.
在上面的实例中,子类Dog覆盖了超类Animal的displayInfo()方法。
当我们使用Dog子类的d1对象调用displayInfo()方法时,将调用Dog子类内部的方法。 不会调用父类内部的方法。
在Dog子类的displayInfo()内部,我们使用了super.displayInfo()来调用父类的displayInfo()。
需要注意的是,Java中的构造函数不会被继承。因此,在Java中不存在诸如构造函数重写之类的问题。
但是,我们可以从其子类中调用超类的构造函数。为此,我们使用super()。要了解更多信息,请访问Java super关键字。
在父类及其子类中声明的相同方法可以具有不同的访问说明符。但是,有一个限制。
我们只能,在提供比父类的访问说明符更大的访问权限的子类中使用的那些访问说明符。 例如,
假设父类中的方法myClass()被声明为protected。然后,myClass()子类中的相同方法可以是 public 或 protected,但不能是private。
class Animal { protected void displayInfo() { System.out.println("I am an animal."); } } class Dog extends Animal { public void displayInfo() { System.out.println("I am a dog."); } } class Main { public static void main(String[] args) { Dog d1 = new Dog(); d1.displayInfo(); } }
输出:
I am a dog.
在上面的示例中,子类Dog重写了父类Animal的displayInfo()方法。
每当我们使用d1(子类的对象)调用displayInfo()时,就会调用子类内部的方法。
注意,displayInfo()在Animal父类中声明为受保护的(protected)。该方法在Dog子类中具有公共访问说明符(public)。这是允许的,因为public提供了比protected更大的访问权限。
在Java中,抽象类被创建为其他类的父类(基类)。而且,如果类包含抽象方法,则必须重写它。
在后面的教程中,我们将学习有关抽象类和抽象方法的重写的更多信息。