携手创作,共同成长!这是我参与「掘金日新计划 · 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
方法。
3.3 不能重写静态方法
使用 static 修饰的方法不能重写
再着来说,静态方法没有重写的意义
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()");}
}