按照软件构造课程中的定义,重载是ad-hoc polymorphism,即一个功能可以以多种形式实现。
例子
public class OverloadExample {
public static void main(String args[]) {
System.out.println(add("C","D"));
System.out.println(add("C","D","E"));
System.out.println(add(2,3));
}
public static String add(String c, String d) {
return c.concat(d);
}
public static String add(String c, String d, String e){
return c.concat(d).concat(e);
}
public static int add(int a, int b) {
return a+b;
}
}
同时也可以说重载是静态多态,在程序的编译阶段的静态类型检查中决定使用哪种方法。与之对应的overriding则是动态的。
然而关于这个说法实际上有不少不同的声音。有的说法是多态必须具备三大特征:子类继承父类,子类覆盖父类,父类指向子类。如果是这样的话,就说明只有继承关系才是多态的先决条件。也有说法是重载因为针对的是方法,违反了面向对象的概念。而面向对象的三大特性之一是多态,由此可见,重载不是面向对象,而是面向方法。所以overloading不是多态。
讨论这个问题的时候,首先看一下overloading的性质。
Rules in function overloading:
the overloaded function must differ either by the arity or data types – MUST change the argument list. 不同的参数列表
– CAN change the return type. 相同/不同的返回值类型
– CAN change the access modifier. 相同/不同的public/private/protected
– CAN declare new or broader checked exceptions. 异常
– A method can be overloaded in the same class or in a subclass. 可以在同一个类内重载,也可在子类中重载
例子
int add(int x,int y){return x+y;}
int add(int x,int y,int z){return x+y+z;}
double add(double x,double y){return x+y;}
关于静态多态和动态多态:本课程中介绍overloading是静态多态。编译器根据方法不同的参数表, 对同名方法的名称做修饰,实际上对于编译器而言,重载的方法是不同的方法,它们的入口地址也不一样,即静态绑定。根据《Java编程思想》中的说法:“不要犯傻,如果它不是晚绑定,它就不是多态。”重载就不算多态。而overriding中,解释器在运行的时候才能确定下来调用的是父类的还是子类的同名方法,因此是动态绑定,属于多态。
根据我的理解,传统上的多态指的应该是父类和子类的灵活的角色扮演,子类拥有很多隐式父类的功能, 那么你当然能扮演它们之中的某一个角色。而如果将这个角色的理解扩展到方法上,同一个类里的方法之间的共性也可以理解为一种多态,是方法的多态性的体现。这些不同说法应该是理论发展的过程。我们尊重不同的声音,但是在《软件构造》课程中,应当将overloading理解为ad-hoc polymorphism,是一种多态。