理解Java多态
多态又称Polymophism,poly意思为多,polymophism即多种形态的意思。一种类型引用因为指向不同的子类,表现出不同的形态,使用不同的方法。
什么是多态
多态建议我们编码时使用common interface(公共接口)而不是concrete implementation(具体实现)。如果我们依赖具体实现来编码,则当我们需要增加common interface的新的实现时,我们需要复制和改变已有代码。程序的可扩展性大大降低。
StackOverflow上关于什么是多态的一个例子很容易记忆。
public abstract class Human{ ... public abstract void goPee(); } /* 抽象方法goPee()对于Human没有实现,它只对男女这两个子类有具体的不同的实现。
Human也是一个抽象类,因为人只有男或女这两个类,不能创建一个既不是男也不是女的Human。 所以我们通过使用抽象类延迟了实现。*/ public class Female extends Human{ ... @Override public void goPee(){ System.out.println("Sit Down"); } } public class Female extends Human{ ... @Override public void goPee(){ System.out.println("Sit Down"); } } //创建一组人要去尿尿 public static void main(String[] args){ ArrayList<Human> group = new ArrayList<Human>(); group.add(new Male()); group.add(new Female()); // ... add more... // tell the class to take a pee break for (Human person : group) person.goPee(); }
运行结果:
Stand Up
Sit Down
...
Java如何实现多态
Java支持实现多态的三个必要条件:继承(inheritance),重写(override),向上转型(upcasting)
继承:
java只支持单继承,即子类和超类之间的关系是“Is-a”的关系。
重写:
父类中的方法会原封不动地被子类继承拥有,但如果子类想做一定的修改,就需要采用方法的重写。父类中的某方法如果与子类中的方法有相同的名称和参数,则该方法被重写。
如果需要在子类中使用被覆盖的父类方法,则可使用super()关键字。子类函数的访问修饰权限不能少于父类。(试想如果一个父类中的方法为public,而在子类中重写为private,则父类类型的引用变量不能调用子类实例对象的方法,导致出错。)
向上转型:
形象化理解即为超类实际上是子类的子集,因为超类的成员都是子类的成员,所以类似Animal cat = new Cat();这样的向上转型是安全的,因为父类引用变量可以操作的成员一定在子类中。与此相反的向下转型则需要使用Instanceof来判断是否安全。
动态绑定:
动态绑定又称后期绑定,是指编译器在编译期间不知道要调用哪个方法,直到运行时才能确定。方法的动态绑定是基于实例对象类型,而不是对象引用的类型。基本上实例方法都在运行时绑定,而private方法,static方法,final方法都在编译时期绑定,称为静态绑定或后期绑定。这也是为什么private, static, final方法不允许重写。
当超类对象引用变量引用子类的对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的成员方法必须在超类中定义过,也就是说被子类覆盖的方法。
总结:
以上机制允许java运行期间执行某个类的成员方法,而不是编码时期声明类型决定。(Method overriding allows java invoke method based on a perticular object at run-time instead of declared type while coding.)
例子:
public class TradingSystem{ public String getDescription(){ return "electronic trading system"; } } public class DirectMarketAccessSystem extends TradingSystem{ public String getDescription(){ return "direct market access system"; } } public class CommodityTradingSystem extends TradingSystem{ public String getDescription(){ return "Futures trading system"; } }
何时使用多态:
- 使用超类作为方法参数,可以在方法内调用不同类的成员方法。
public void showDescription(TradingSystem tradingSystem){ tradingSystem.description(); }
- 使用超类声明变量,可以接收Factory method的返回值。
String systemName = Configuration.getSystemName(); TradingSystem system = TradingSystemFactory.getSystem(systemName);
- 使用超类作为返回值
public TradingSystem getSystem(String name){ //code to return appropriate implementation }
这篇文章提供了一个很好的例子
对于Java实现讲解的好文章
参考文章:
What is polymorphism in Java? Method overloading or overriding?
Java 重写(Override)与重载(Overload)