什么是多态
多态调用表现为:表面看起来你对父类调用了一个方法,实际上在方法的响应过程中由子类(方法的接收者)根据自己是谁,自行决定要怎么去响应它。其中方法的接收者是xxx.f()
中的xxx
。
Shape shape = new Circle(1);
shape.getArea();
- 静态方法是没有多态的
- 参数是静态绑定的,接收者是动态绑定的。换句话说多态只对方法的接收者生效。又换句话说多态只选择接收者的类型,不选择参数的类型。
举个例子:如下代码,试想会输出什么结果?答案是:I am Sub, the param is ParamBase
。参数的选择是由方法重载所决定的,选择的参数是最不用转换(匹配度最高)的那一个。
public class Base {
public void print(ParamBase param){
System.out.println("I am Base, the param is ParamBase");
}
public void print(ParamSub param){
System.out.println("I am Base, the param is ParamSub");
}
}
public class Sub extends Base {
@Override
public void print(ParamBase param) {
System.out.println("I am Sub, the param is ParamBase");
}
@Override
public void print(ParamSub param) {
System.out.println("I am Sub, the param is ParamSub");
}
}
public class Main {
public static void main(String[] args) {
Base obj = new Sub();
ParamBase param = new ParamSub();
obj.print(param);
}
}
再举一个实际的例子:HashSet.addAll
方法。HashSet的addAll方法是从AbstractCollection
中继承过来的,它本身没有重写。AbstractCollection
有一个add
方法,addAll
方法又调用了add
方法。Hashset
重写了add
方法。这可能听起来有点绕,我们用一张图说明清楚。问题是HashSet.addAll()
这个语句调用的add
方法是HashSet
还是AbstractCollection
的?答案是:Hashset
。
总结一下:多态的意思是根据当前的类型决定调用哪个方法。任何时候实例方法的选择,都是由当前对象根据自己实际的类型来决定去调用哪个方法的。
多态实战:策略模式
使用策略模式重构这个方法,实现三个策略:
- NoDiscountStrategy 不打折
- Discount95Strategy 全场95折
- OnlyVipDiscountStrategy 只有VIP打95折,其他人保持原价
public class PriceCalculator {
public static int calculatePrice(DiscountStrategy strategy, int price, User user){
// 这里体现了多态的思想。
return strategy.discount(price, user);
}
}
public class DiscountStrategy {
public int discount(int price, User user) {
throw new UnsupportedOperationException();
}
}
public class NoDiscountStrategy extends DiscountStrategy {
@Override
public int discount(int price, User user) {
return price;
}
}
public class Discount95Strategy extends DiscountStrategy {
@Override
public int discount(int price, User user) {
return (int)(price * 0.95);
}
}
public class OnlyVipDiscountStrategy extends DiscountStrategy {
@Override
public int discount(int price, User user) {
if (user.isVip()) {
return (int) (price * 0.95);
} else {
return price;
}
}
}
再举一个JDK中线程池ThreadPoolExecutor
的例子:其中几个个构造器中有RejectedExecutionHandler
这样一个参数,这个参数就是一种策略模式。
分别有以下几种策略:
网友评论