Java基础篇:重写

41 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

1.介绍

在任何面向对象的编程语言中, 重写 是指它允许子类对父类已有方法的特定实现。
当子类中的方法与其父类中的方法具有相同的名称,参数或签名以及相同的返回类型(或子类型)时,则称子类中的方法重写父类中的方法。

class Language{
  void speak(){}
}
class Chinese extends Language{
	void speak(){} // 重写
}

2. 方法重写是运行时多态

执行的方法体的将由用于调用它的对象确定。如果使用父类的对象来调用该方法,则将执行父类中的版本,但是如果使用子类的对象来调用该方法,则将执行子类中的版本。换句话说,决定要执行哪个版本的重写方法的是被引用对象的类型(而不是引用变量的类型)。

// 一个简单的Java程序来演示
// Java中的方法重写

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

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

// Driver class
class Main {
	public static void main(String[] args)
	{
		//如果引用了父类型到父对象
		// 调用show()
		Parent obj1 = new Parent();
		obj1.show();

		// 引用了父类对象到子对象,实现运行时多态。
		Parent obj2 = new Child();
		obj2.show();
	}
}

输出:

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

3.规则

3.1 重写与访问修饰符

重写方法的访问修饰符可以允许比 重写的方法更广泛 。例如,父类方法修饰符为 public , 子类的修饰符就不能比 public  小,这样做会产生编译时错误。例如下述代码:

public class TestOverride {
    public void hello(){
        System.out.println("Hello");
    }

    class TestChild extends TestOverride{
        private void hello(){
            System.out.println("Hello");
        }
    }
}

编译错误

'hello()' in 'com.github.gleans.TestOverride.TestChild' clashes with 'hello()' in 'com.github.gleans.TestOverride'; attempting to assign weaker access privileges ('private'); was 'public'

attempting to assign weaker access privileges, 意思就是你试图分配更小的访问权限给子类。

3.2 不能覆盖final方法

如果我们不希望某个方法被重写,则将其声明为 final  方法。 image.png

3.3 不能重写静态方法

使用 static 修饰的方法不能重写 image.png 再着来说,静态方法没有重写的意义

3.4 私有方法不能重写

首先我们来会回忆一下,私有化属性的访问权限,应该是当前类,所以子类不在当前类范围内,直接宣判,私有方法不能重写。

3.5 构造方法不能重写

首先,子类与父类的构造方法的 方法名 都不可能相同。你说或许可能,wtF,我们来复习一下构造函数是什么,方法名与类名一致,所以子父类类名相同,世上有两片相同的树叶了吗?

4. 拓展

4.1 支持多子多孙系列

class 父类 {
	void show(){ System.out.println("父类 show()");}
}

class 子类 extends 父类 {
	void show() { System.out.println("子类 show()"); }
}

class 孙类 extends 子类 {
	void show(){ System.out.println("孙类 show()");}
}