Java基础之多态的实现重载 vs 重写

2019-08-05  本文已影响0人  最后的轻语_dd43

该项目源码地址:https://github.com/lastwhispers/code/tree/master/java-basic

前言

重载(overload)和重写(override)这两个概念有时候经常会搞混,这里记录一下。

在写这个笔记之前一直很纠结“重载”到底属不属于多态?
有人说属于、有人说不属于。https://bbs.csdn.net/topics/300257765
这个帖子讨论的很激烈。我觉得这个36楼的大哥说的有理,这些都是些“名词之争”。

多态是指只有到运行时才能确定要执行的代码,即指的是后期绑定,这样Overload就不属于多态。
在C++语言中,如果不将Override方法声明为Virtual的,也应该不属于多态。
不过话又说回来,很多书上说overload是方法意义上的多态,都是些名词之争
关键是自己要理解各自的意义,会用万岁!!

在stackoverflow也有类似观点
https://stackoverflow.com/questions/2400284/is-method-overloading-considered-polymorphism

"Polymorphism" is just a word and doesn't have a globally agreed-upon, precise definition. You will not be enlightened by either a "yes" or a "no" answer to your question because the difference will be in the chosen definition of "polymorphism" and not in the essence of method overloading as a feature of any particular language. You can see the evidence of that in most of the other answers here, each introducing its own definition and then evaluating the language feature against it.
“多态性”只是一个词,并没有全球一致的精确定义。 你不会被你的问题的“是”或“否”答案所启发,因为差异将在所选择的“多态性”定义中,而不是作为任何特定语言的特征的方法重载的本质。 你可以在这里看到大多数其他答案中的证据,每个答案都引入了自己的定义,然后根据它来评估语言特征。

也就是说“多态性”并没有一个像数学公式一样的很严格的定义,可能在不同的面向对象编程语言中定义不一样,然后实现也不一样。

所以,本文以"重载是编译时的多态实现,重写是运行时的多态实现"的观点进行撰述。

1. 方法重载

什么是方法重载?
方法的重载是指在一个类中,出现多个方法名相同,但参数个数或参数类型不同的方法,则称为方法的重载。Java在执行具有重载关系的方法时,将根据调用参数的个数和类型区分具体执行的是哪个方法。

方法重载规则:方法名称必须相同,参数个数、次序、类型任意一项不同;
无关条件:访问修饰符、返回值、抛异常;

重载规则实例

public void overloadFun() {
         // 无参函数
}

加上参数,对overloadFun()方法进行重载

public void overloadFun(Long id) {
        // 重载overloadFun,参数个数不同
}

更换参数类型,对overloadFun()方法进行重载

public void overloadFun(Integer id) {
        // 重载overloadFun,参数类型不同
}

增加参数个数,对overloadFun()方法进行重载

public void overloadFun(Long id, String name) {
      // 重载overloadFun,参数个数不同
}

更换参数次序,对overloadFun()方法进行重载

public void overloadFun(String name, Long id) {
        // 重载overloadFun,参数顺序不同
}

无关条件实例

// 抛出异常不同,并不能构成函数重载
public void overloadFun() throws Exception{
}
// 访问修饰符不同,并不能构成函数重载
private void overloadFun(Integer id) {
}
// 返回值不同,并不能构成函数重载
public int overloadFun(){
    return 0;
}

2. 方法重写

什么是方法重写?
当子类继承父类中所有可能被子类访问的成员方法时,如果子类的方法名与父类的方法名相同,那么子类就不能继承父类的方法,此时,称子类的方法重写了父类的方法。重写体现了子类补充或者改变父类方法的能力,通过重写,可以使一个方法在不同的子类中表现出不同的行为。

方法重写规则:

实例

先编写一个父类,注意该方法时使用protected修饰,并且抛出ArithmeticException。

public class SuperClass {
    protected int overrideFun(int a, int b) throws ArithmeticException {
        int divisor = a / b;
        return divisor;
    }
}

再编写一个子类继承SuperClass并重写overrideFun方法。

public class SubClass extends SuperClass {

    @Override
    protected int overrideFun(int a, int b) {
        if (b == 0) {
            return Integer.MAX_VALUE;//说明除数为0
        }
        return a / b;
    }
}

通常子类重写父类方法是因为父类的方法满足不了子类的需求,子类对父类的方法进行重写。所以让父类除法时没有做除数非0的判断,让子类重写父类的方法,进行除数非0的判断。

我们再来试试重写对访问修饰符和异常的要求。

重写方法的访问修饰符权限范围必须大于等于父类方法。(访问修饰符权限public>protected>private)

我们将子类重写的overrideFun方法访问修饰符改为“private”。

重写方法的访问修饰符权限范围必须大于等于父类方法

此时就会报错,因为父类的引用指向子类对象,调用子类对象方法会访问不到,违背了多态性。

重写方法抛出的异常范围不能大于父类方法

父类的overrideFun方法抛出了ArithmeticException,我们在子类的overrideFun方法抛出范围更大Exception。

重写方法抛出的异常范围不能大于父类方法

此时就会报错,因为重写方法抛出的异常范围大于父类方法。

3. 总结

多态:

重载(overload):

重写(override):

参考

https://blog.csdn.net/lijing742180/article/details/90049341

https://bbs.csdn.net/topics/300257765

https://stackoverflow.com/questions/2400284/is-method-overloading-considered-polymorphism

上一篇下一篇

猜你喜欢

热点阅读