重载重写是非常基础的知识
本文从 访问控制修饰符、返回值、方法名、参数列表、异常类型四个方面对重载和重写进行解析
1.重写
1.1.里氏替换原则
“派生类(子类)对象可以在程式中代替其基类(超类)对象。”
(使用到父类对象的地方可以透明的替换为子类对象)
1.2.重写
子类覆盖父类的方法
要求:
- 方法名相同
- 参数个数、种类、排列顺序相同
重点
- 返回值类型必须是父类对应方法的返回值类型或其子类
在使用父类对象的地方替换为子类对象,要做到透明替换,则子类方法的返回值要能被合法接收,这就要求子类方法的返回值是父类对应方法返回值类型或其子类
// 注意观察返回值类型,并对应里氏替换原则思考
// Number是Integer的父类
// 如果将父类方法的返回值类型与子类方法的返回值类型交换则会报错
class Father {
public Number fun () {
return 1;
}
}
class Child extends Father {
@Override
public Integer fun() {
return 1;
}
}
class Child extends Father {
@Override
public Number fun() {
return 1;
}
}
- 子类重写父类方法时要求访问控制修饰符不能比父类更严格(private > default > protected > public)
在使用父类对象的地方替换为子类对象,要做到透明替换,这就要求父类对象能访问到某方法,子类对象同样能够访问到重写后的对应方法。
// 注意观察访问控制修饰符,并对应里氏替换原则思考
class Base {
private void privateFun() {
System.out.println("Base privateFun");
}
void defaultFun() {
System.out.println("Base defaultFun");
}
protected void protectedFun() {
System.out.println("Base protectedFun");
}
public void publicFun() {
System.out.println("Base publicFun");
}
}
class Child extends Base {
// privateFun无法重写
// 该方法使用default、protected、public修饰都可以
@Override
void defaultFun() {
System.out.println("Child defaultFun");
}
// 该方法使用protected、public修饰都可以
@Override
public void protectedFun() {
System.out.println("Child protectedFun");
}
// 该方法只能使用public修饰
@Override
public void publicFun() {
System.out.println("Child publicFun");
}
}
- 子类重写父类方法时要求其抛出的异常范围小于等于父类
class Base {
void exceptionFun() throws Exception{
}
}
class Child extends Base {
@Override
void exceptionFun() throws RuntimeException{
}
}
2.重载
2.1.方法签名
方法名+形参列表
对访问控制修饰符、返回值类型、异常类型 未作要求
对于同名不同类、同类不同名的方法,方法签名的意义并不是很大,但是对于重载方法来说,方法签名的意义就十分巨大了。由于重载方法之间的方法名是相同的,那么我们势必要从构成方法的其他几个要素中找到另一个要素与方法名组成能够唯一标示方法的签名,方法体当然不予考虑。那么就是形参列表和返回值了,但是由于对于调用方法的人来说,方法的形参数据类型列表的重要程度要远远高于返回值,所以方法签名就由方法名+形参列表构成,也就是说,方法名和形参数据类型列表可以唯一的确定一个方法,与方法的返回值一点关系都没有,这是判断重载重要依据。
2.2.重载
重载,从简单说,就是同一个类中函数或者方法有相同的名称,但是参数列表不相同的情形。