📅  最后修改于: 2020-03-19 12:26:44             🧑  作者: Mango
在任何面向对象的编程语言中,重写Override都是一项功能,它允许子类提供其超类或父类之一已提供的方法的特定实现。当子类中的方法与其父类中的方法具有相同的名称、相同的参数或签名以及相同的返回类型(或子类型)时,则该子类中的方法被称为重写父类中的方法。
方法重写是Java实现运行时多态的一种方法。执行方法的版本将由调用它的对象确定。如果使用父类的对象来调用该方法,则将执行父类中的版本,但是如果使用子类的对象来调用该方法,则将执行子类中的版本。换句话说,确定要执行哪个版本的重写方法,取决于被引用对象的类型(而不是引用变量的类型)。
// Java展示方法重写
class Parent {
void show()
{
System.out.println("父类的 show()");
}
}
// 集成类class
class Child extends Parent {
// 重写父类的show()
@Override
void show()
{
System.out.println("子类的 show()");
}
}
// 测试代码
class Main {
public static void main(String[] args)
{
Parent obj1 = new Parent();
obj1.show();
// 多态.
Parent obj2 = new Child();
obj2.show();
}
}
输出:
父类的 show()
子类的 show()
方法重写的规则:
// Java展示重写和访问修饰符
class Parent {
// private 方法没有被重写
private void m1()
{
System.out.println("父类的 m1()");
}
protected void m2()
{
System.out.println("父类的 m2()");
}
}
class Child extends Parent {
// 新的m1()方法
private void m1()
{
System.out.println("子类的 m1()");
}
// 重写方法
@Override
public void m2()
{
System.out.println("子类的 m2()");
}
}
// 测试代码
class Main {
public static void main(String[] args)
{
Parent obj1 = new Parent();
obj1.m2();
Parent obj2 = new Child();
obj2.m2();
}
}
输出:
父类的 m2()
子类的 m2()
// Java展示final修饰符不能被重写
class Parent {
// 无法被重写
final void show() {}
}
class Child extends Parent {
// 这会报错
void show() {}
}
输出:
13: error: show() in Child cannot override show() in Parent
void show() { }
^
overridden method is final
超类实例方法 | 超类静态方法 | |
---|---|---|
子类实例方法 | 重写 | 产生编译时错误 |
子类静态方法 | 产生编译时错误 | 隐藏 |
// Java展示如果一个派生类重写了static方法,该方法被隐藏了
class Parent {
// Static方法
static void m1()
{
System.out.println("父类 "
+ "静态 m1()");
}
// 非静态方法
void m2()
{
System.out.println("父类 "
+ "非静态实例 m2()");
}
}
class Child extends Parent {
// 如下方法隐藏了父类的m1方法
static void m1()
{
System.out.println("子类静态 m1()");
}
// 如下方法重写了父类的m2()
@Override
public void m2()
{
System.out.println("子类 "
+ "非静态实例 m2()");
}
}
// 测试代码
class Main {
public static void main(String[] args)
{
Parent obj1 = new Child();
obj1.m1();
obj1.m2();
}
}
输出:
父类 静态 m1()
子类 非静态实例 m2()
// Java展示子类调用被重写的父类方法
// 基类Class
class Parent {
void show()
{
System.out.println("父类 show()");
}
}
// 子类集成
class Child extends Parent {
// 这个方法重写父类的show()
@Override
void show()
{
super.show();
System.out.println("子类 show()");
}
}
// 测试代码
class Main {
public static void main(String[] args)
{
Parent obj = new Child();
obj.show();
}
}
输出:
父类 show()
子类 show()
// Java展示父类没有抛出异常
class Parent {
void m1()
{
System.out.println("父类 m1()");
}
void m2()
{
System.out.println("父类 m2()");
}
}
class Child extends Parent {
@Override
// 报出未检查的异常是可以的
void m1() throws ArithmeticException
{
System.out.println("子类 m1()");
}
@Override
// 编译错误
void m2() throws Exception
{
System.out.println("子类 m2");
}
}
输出:
error: m2() in Child cannot override m2() in Parent
void m2() throws Exception{ System.out.println("子类 m2");}
^
overridden method does not throw Exception
// Java展示父类引发异常
class Parent {
void m1() throws RuntimeException
{
System.out.println("父类 m1()");
}
}
class Child1 extends Parent {
@Override
// 没问题
void m1() throws RuntimeException
{
System.out.println("子类1 m1()");
}
}
class Child2 extends Parent {
@Override
// 没问题
void m1() throws ArithmeticException
{
System.out.println("子类2 m1()");
}
}
class Child3 extends Parent {
@Override
// 没问题
void m1()
{
System.out.println("子类3 m1()");
}
}
class Child4 extends Parent {
@Override
// 编译错误
void m1() throws Exception
{
System.out.println("子类4 m1()");
}
}
输出:
error: m1() in Child4 cannot override m1() in Parent
void m1() throws Exception
^
overridden method does not throw Exception
注意 :
// Java程序展示多级重写
// 基类
class Parent {
void show()
{
System.out.println("父类 show()");
}
}
// 集成
class Child extends Parent {
// 这个方法重写show()
void show() { System.out.println("子类 show()"); }
}
// Inherited class
class GrandChild extends Child {
// 重写父类show()
void show()
{
System.out.println("孙子类 show()");
}
}
// 测试类
class Main {
public static void main(String[] args)
{
Parent obj1 = new GrandChild();
obj1.show();
}
}
输出:
孙子类 show()
如前所述,重写的方法允许Java支持运行时多态。多态性对于面向对象的编程至关重要,原因之一是:多态性允许通用类指定对其所有派生类通用的方法,同时允许子类定义某些或所有这些方法的特定实现。重写方法是Java实现多态性的“一个接口,多个方法”方面的另一种方式。
动态方法分派是面向对象设计带来的最强大的机制之一,可影响代码的重用性和鲁棒性。存在的代码库能够在保持干净的抽象接口的同时不重新编译的情况下,调用新类实例上的方法的函数是一种强大的提现。
重写方法使我们可以调用任何派生类的方法,甚至不知道派生类对象的类型。
何时应用方法重写?(带有示例)
重写和继承:成功应用多态性的部分关键是要了解,超类和子类形成了一个层次结构,该层次结构从较小的专业化过渡到较大的专业化。如果正确使用,超类将提供子类可以直接使用的所有元素。它还定义了派生类必须自己实现的那些方法。这使子类可以灵活地定义其方法,但仍然可以强制使用一致的接口。因此,通过将继承与重写的方法相结合,超类可以定义将由其所有子类使用的方法的一般形式。
让我们看一个使用方法重写的更实际的示例。考虑一个组织的雇员管理软件,让代码具有一个简单的基类Employee,该类具有诸如raiseSalary(),transfer(),promove()等方法。不同类型的雇员,例如Manager,Engineer 、…等可能具有基类Employee中存在的方法的实现。在我们完整的软件中,我们只需要在各处传递一个员工列表并调用适当的方法,甚至不知道员工的类型。
例如,我们可以通过遍历员工列表轻松地提高所有员工的薪水。每种类型的员工都可以在其类中拥有自己的逻辑,我们不必担心,因为如果针对特定员工类型提供了raiseSalary(),则仅会调用该方法。
// Java展示重写
// 基类
class Employee {
public static int base = 10000;
int salary()
{
return base;
}
}
// 继承类
class Manager extends Employee {
// 重写基类 salary()
int salary()
{
return base + 20000;
}
}
// 继承
class Clerk extends Employee {
// 重写父类的salary()
int salary()
{
return base + 10000;
}
}
// 测试代码
class Main {
static void printSalary(Employee e)
{
System.out.println(e.salary());
}
public static void main(String[] args)
{
Employee obj1 = new Manager();
System.out.print("经理工资 : ");
printSalary(obj1);
Employee obj2 = new Clerk();
System.out.print("员工工资 : ");
printSalary(obj2);
}
}
输出:
经理工资 : 30000
员工工资 : 20000