建议6 覆写变长方法也循规蹈矩
思考一下以下代码:
class Base
{
void fun(int price, int...discounts)
{
System.out.println("Base...fun");
}
}
class Sub extends Base
{
@override
void fun(int price, int[] discounts)
{
System.out.println("Sub...fun");
}
}
Base base = new Sub();
base.fun(100, 50);
Sub sub = new Sub();
sub.fun(100, 50);
该程序有什么问题吗? ---- 编译通不过。 问题出在什么地方呢?
这里@Override注解是正确的,因为父类的CalPrice编译成字节码后的形参是一个int类型加上一个int数组类型,所以跟子类的参数列表是相同的,只是Eclipse会提示这不是一种很好的编程风格。
真正的问题是出在 sub.fun(100, 50) 这条语句上,提示找不到 fun(int, int) 方法。为什么通过父类调用就没问题?Why??
事实上,base对象是把子类对象做了向上转型,此时实参50传入变长参数,再经由编译器“猜测”转变成“ {50} ”数组,由子类执行。
但是直接调用子类的情况,这时编译器并不会把 50 做类型转换,因为数组本身也是一个对象,编译器还没有聪明到要在两个没有继承关系的类之间做转换。
这是一个特例,覆写的方法参数列表竟然与父类不相同,这违背了覆写的定义,并且会引发莫名其妙的错误。所以读者在对变长参数进行覆写时,如果要使用此类似的方法,请找一个小黑屋仔细想想是不是一定要如此。
所以,覆写的方法参数与父类相同、不仅仅是类型、数量,还包括显示形式。