在上一教程中,我们了解了继承。继承是一个OOP属性,它使我们可以从现有的类(超类)派生一个新的类(子类)。子类继承超类的属性和方法。
现在,如果在超类类和子类类中都定义了相同的方法,则子类类的方法将覆盖超类的方法。这称为方法覆盖。
示例1:方法覆盖
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.
在上述程序中, 动物超类和Dog子类中都存在displayInfo()
方法。
当我们使用d1对象(子类的对象displayInfo()
调用displayInfo()
,将调用子类Dog中的方法。子类的displayInfo()
方法将覆盖超类的相同方法。
请注意,在我们的示例中使用了@Override
注释。在Java中,注释是我们用于向编译器提供信息的元数据。这里, @Override
批注指定编译器,该批注之后的方法将覆盖超类的方法。
使用@Override
不是强制性的。但是,当我们使用此方法时,该方法应遵循所有覆盖规则。否则,编译器将生成错误。
Java覆盖规则
- 超类和子类都必须具有相同的方法名称,相同的返回类型和相同的参数列表。
- 我们不能覆盖声明为
final
和static
的方法。
- 我们应该始终重写超类的抽象方法(将在以后的教程中进行讨论)。
Java覆盖中的超级关键字
final
和static
的方法。 在Java中执行覆盖时出现的一个常见问题是:
覆盖后可以访问超类的方法吗?
好吧,答案是肯定的 。要从子类访问超类的方法,我们使用super
关键字。
示例2:使用超级关键字
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()
。
当我们调用方法displayInfo()
使用的狗的子类对象D1,内部的狗的子类被称为方法;不会调用超类内部的方法。
在Dog子类的displayInfo()
内部,我们使用了super.displayInfo()
来调用超类的displayInfo()
。
重要的是要注意,Java中的构造函数不会被继承。因此,在Java中不存在诸如构造函数重写之类的问题。
但是,我们可以从其子类中调用超类的构造函数。为此,我们使用super()
。要了解更多信息,请访问Java super关键字。
方法覆盖中的访问说明符
在超类及其子类中声明的相同方法可以具有不同的访问说明符。但是,有一个限制。
我们只能在提供比超类的访问说明符更大的访问权限的子类中使用那些访问说明符。例如,
假设超类中的方法myClass()
被声明为protected
。然后,子类中的相同方法myClass()
可以是public
或protected
,但不能是private
。
示例3:覆盖中的访问说明符
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()
时,就会调用子类内部的方法。
注意,在动物超类中将displayInfo()
声明为protected
的。相同的方法在Dog子类中具有public
访问说明符。这是可能的,因为public
提供了比protected
更大的访问权限。
覆盖抽象方法
在Java中,抽象类被创建为其他类的超类。并且,如果类包含抽象方法,则必须重写它。
在后面的教程中,我们将学习有关抽象类和抽象方法的重写的更多信息。