理解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";
   }
}

何时使用多态:

  1. 使用超类作为方法参数,可以在方法内调用不同类的成员方法。
    public void showDescription(TradingSystem tradingSystem){
       tradingSystem.description();
    }
  2. 使用超类声明变量,可以接收Factory method的返回值。
    String systemName = Configuration.getSystemName();
    TradingSystem system = TradingSystemFactory.getSystem(systemName);

     

  3. 使用超类作为返回值
    public TradingSystem getSystem(String name){
       //code to return appropriate implementation
    }

     

这篇文章提供了一个很好的例子

对于Java实现讲解的好文章

参考文章:

  What is polymorphism in Java? Method overloading or overriding?

  动态绑定vs静态绑定

  Java中重载与重写的区别

  Java 重写(Override)与重载(Overload)

  Java多态性详解--父类引用子类对象

 

 

posted on 2016-02-18 16:07  jxzheng  阅读(472)  评论(0编辑  收藏  举报

导航