Overriding in Java

原文:geeks4geeks

子类可以重新定义父类的方法,这种属性被称为方法重写(Overriding)。签名(返回类型,参数类型,参数数量)保持和父类中定义的一致,完成方法重写以实现运行时多态(重写的方法是根据调用它的对象被调用,而不是根据它的引用类型)。

// 简单的演示重写的例子

// 父类
class Parent{
  void show() { 
    System.out.println("Parent's show()"); 
  }
}

// 子类
class Child extends Parent{
  // 重写父类的方法
  void show() { 
    System.out.println("Child's show()");
  }
}

// 测试类
class Test {
  public static void main(String[] args) {
    // 如果父类引用父类的对象,则父类的 show 方法被调用
    Parent obj1 = new Parent();
    obj1.show();
    // 如果父类引用子类的对象,则子类的 show 方法被调用
    // 这种被称为运行时多态
    Parent obj2 = new Child();
    obj2.show();
  }
}

输出:

Parent's show()
Child's show()
一些有趣的事实:
  • C++ 中需要 virtual 关键字以实现重写或运行时多态。Java 中方法默认是 virtual 的。
  • 可以有多级的重写:
// 简单的演示多级重写的例子

// 父类
class Parent {
  void show() {
    System.out.println("Parent's show()");
  }
}

// 子类
class Child extends Parent {
  // 重写父类的方法 
  void show() {
    System.out.println("Child's show()");
  }
}

// 孙类
class GrandChild extends Child {
  // 重写子类的方法
  void show() { 
    System.out.println("GrandChild's show()");
  }
}

// 测试类
class Test {
  public static void main(String[] args) {
    Parent obj1 = new GrandChild();
    obj1.show();
  }
}

输出:

GrandChild's show()
  • 如果不想让一个方法被重载,可以用 final 关键字修饰它
// 简单的演示 final 关键字重写的例子

class Parent {
  // 不能被重写
  final void show() { }
}

class Child extends Parent {
  // 会产生错误
  void show() { }
}

输出:

error: show() in Child cannot override show() in Parent
  void show() {  }
       ^
  overridden method is final
  • 重写的方法的访问限制不能收窄,只能扩大。如父类中是 protected 方法 ,子类不能以 private 限制符重写方法。
  • Private 的方法不能被重写,因为在 private 方法在编译时绑定会它的引用类型。
  • 我们可以给子类中与父类相同签名的方法加上 static 关键词,但这不认为是重写,因为没有任何运行时多态。
  • 我们可以在重写的方法中使用 super 关键字调用父类的方法。
// 简单的例子演示 super 关键字重写的例子

// 父类
class Parent {
void show() {
  System.out.println("Parent's show()");
  }
}

// 子类
class Child extends Parent {
// 重写父类的 show 方法
  void show() {
    super.show();
    System.out.println("Child's show()");
  }
}

// 测试类
class Test {
  public static void main(String[] args) {
    Parent obj = new Child();
    obj.show();
  }
}

输出:

Parent's show()
Child's show()

应用

重写的方法允许我们调用任何派生类的方法,甚至不必知道派生类对象的种类。

Overriding in Java_第1张图片
JavaOVerriding.jpg

上图的管理软件中基类 Employee 有不同的方法,如 raiseSalary(), transfer(), promote(), salary()等。不同的子类 Manager 和 Clerk 可能对这些父类的方法有自己的实现。在实际使用场景中,我们只需要传递一份完整的员工名单,而不必知道他所属的类型是 Manager 或 Clerk 之类的。例如,我们只需通过遍历名单给每位员工 raiseSalary(),每位员工都有自己的 raiseSalary() 逻辑,我们不必知道每个员工对应的类型。每个员工只要有 raiseSalary() 方法,便会被调用。

// 简单的演示重写应用的例子

// 基类
class Employee {
  public static int base = 10000;
  int salary() {
    return base;
  }
}

// 派生类
class Manager extends Employee {
  // This method overrides show() of Parent
  int salary() {
    return base + 20000;
  }
}

// 派生类
class Clerk extends Employee {
  // This method overrides show() of Parent
  int salary() {
  return base + 10000;
  }
}

// 测试类
class Test {
  // 打印雇员的薪资
  static void printSalary(Employee e) {
    System.out.println(e.salary());
  }

  public static void main(String[] args) {
    Employee obj1 = new Manager();
    System.out.print("Manager's salary : ");
    printSalary(obj1);

    Employee obj2 = new Clerk();
    System.out.print("Clerk's salary : ");
    printSalary(obj2);
  }
}

输出:

Manager's salary : 30000
Clerk's salary : 20000

你可能感兴趣的:(Overriding in Java)