Java中的方法覆盖

时间:2020-01-09 10:34:45  来源:igfitidea点击:

当子类中的方法与父类中的方法具有相同的名称和签名(参数的相同数量和类型)时,子类将覆盖超类中的方法,此过程称为方法覆盖Java。

Java中的方法重写示例

class A {
  public int add(int a, int b) {
    System.out.println("in add method of the parent class" );
    return a+b;
  }
}

public class B extends A{
  // Overriding method of the parent class
  public int add(int a, int b) {
    System.out.println("in add method of the child class" );
    return a+b;
  }	

  public static void main(String[] args) {
    B obj = new B();
    System.out.println("Add- " + obj.add(9, 3));
  }
}

输出:

in add method of the child class
Add- 12

在该示例中,类A具有方法add(),该方法在子类B中被覆盖。在类型B的对象上调用add()方法时,类B的add()方法将被调用。重写父类A的add()方法。

使用super调用父类方法

我们可以使用super来调用重写方法的父类版本。

class A {
  public void display(String msg) {
    System.out.println("in display method " + msg);
  }
}

public class B extends A{
  // Overriding method of the parent class
  public void display(String msg) {
    // calling parent class method
    super.display("Parent class method");
    System.out.println("in display method " + msg);
  }	

  public static void main(String[] args) {
    B obj = new B();
    obj.display("Child class method");
  }
}

输出:

in display method Parent class method
in display method Child class method

Java中方法重写的规则

  • 当方法名称相同且超级类和子类方法中的签名也相同时,则仅将其视为方法重写。如果方法具有相同的名称,但参数不相同,则将它们视为重载方法,这将成为方法重载。
  • 子类中重写方法的返回类型应该与父类方法的返回类型的子类型相同。在Java中称为协变返回类型。
  • 覆盖方法的可见性无法降低。例如,如果某个方法在超类中是公共的,则子类中被覆盖的方法无法得到保护或者默认设置,因为这将降低可见性。另一方面,如果方法在超类中受保护,则它可以在重写的方法中公开。
  • 如果超类中的方法引发异常,则子类重写的方法可以声明与超类方法中声明的异常相同的子类,或者子类可以声明超类方法中声明的异常的子类型异常。
  • 在超类中声明为final的方法不能在子类中覆盖。

Java中的方法覆盖和运行时多态

Java中的运行时多态性是通过方法重写实现的。必须在运行时而不是在编译时解析哪个重写的方法。此过程在Java中也称为动态方法分派。

超类引用也可以引用子类对象,必须调用的重写方法中的哪一个取决于超类引用当前持有的引用,并且在运行时做出决定。

Java中的方法重写–运行时多态示例

让我们尝试举例说明一下。在该示例中,有一个超类Payment与doPayment(double amount)方法。

此类由三个子类扩展,并且所有子类都实现方法doPayment。

public class Payment {
  void doPayment(double amount) {
    System.out.println("In parent class payment method");
  }
}
// childclass-1
class CashPayment extends Payment {
  @Override
  public void doPayment(double amount) {
    System.out.println("In child class CashPayment- " + amount);
  }
}
//childclass-2
class CCPayment extends Payment {
  @Override
  public void doPayment(double amount) {
    System.out.println("In child class CCPayment- " + amount);
  }
}
//childclass-3
class MobilePayment extends Payment {
  @Override
  public void doPayment(double amount) {
    System.out.println("In child class MobilePayment- " + amount);
  }
}
public class MainClass {
  public static void main(String[] args) {
    // super class reference
    Payment payment;
    // holding CashPayment instance
    payment = new CashPayment();
    payment.doPayment(56.25);
    // holding CCPayment instance
    payment = new CCPayment();
    payment.doPayment(67.89);
    // holding MobilePayment instance
    payment = new MobilePayment();
    payment.doPayment(34);
    // holding super class Payment instance
    payment = new Payment();
    payment.doPayment(116.78);
  }
}

输出:

In child class CashPayment- 56.25
In child class CCPayment- 67.89
In child class MobilePayment- 34.0
In parent class payment method

在MainClass中,声明了一个超类引用变量,该引用变量在不同时间引用不同的子类实例并进行方法调用。调用该子类的方法doPayment(),该方法当时由超类引用引用。