第8章 多态

来源:互联网 发布:java商场系统 jeshop 编辑:程序博客网 时间:2024/05/16 10:37
  • 最近编程时候,遇见了一个问题,当时怎么都想不通。最后,谁知是多态。所以要静心研究下多态。

多态的定义

  • 多态一般分为两种:
    • 编译时的多态:
      • 方法的重载
    • 运行时的多态:
      • 继承
      • 实现接口
  • 我们所说的多态一般是运行时的多态。
  • 要使用多态,在声明对象时就应该遵循一条法则:声明的总是父类类型或接口类型,创建的是实际类型。
  • 面向对象的三大特征: 封装 继承 多态
  • 多态通过分离 做什么 和 怎么做 ,从另外的一个角度将接口和实现分离开来。
  • 封装通过合并特征和行为来创建新的数据类型。“实现隐藏”则是通过将细节“私有化”把接口和实现分离开。
  • 多态的作用是消除类型之间的耦合关系。
  • 多态也叫作动态绑定,后期绑定,运行时绑定。
  • 首先是一个多态的例子:
class Instrument {  public void play(Note n) {    print("Instrument.play()");  }}public class Wind extends Instrument {  public void play(Note n) {    System.out.println("Wind.play() " + n);  }}public class Music {  public static void tune(Instrument i) {    i.play(Note.MIDDLE_C);  }  public static void main(String[] args) {    Wind flute = new Wind();    tune(flute); // Upcasting  }}// Output://Wind.play() MIDDLE_C

方法调用绑定

  • 将一个方法同一个方法主体关联起来叫做 绑定。如果程序执行前进行绑定的话,叫做前期绑定。(这一般是面向过程语言的绑定过程)

  • 后期绑定:运行时根据对象的类型进行绑定。

  • 后期绑定在不同的语言中事先有所不同,但是想象一下就会得知,不知怎样必须在对象中安置某种类型信息。
  • java中出了 finalstatic 方法之外,所有的方法都是后期绑定。
  • 声明为final方法的好处:防止其他人覆盖该方法。但是更重要的一点是:这样做可以有效地关闭动态绑定。

多态的“缺陷”

  • private方法被自动的认为是final方法,对于导出类是屏蔽的。
public class PrivateOverride {  private void f() { print("private f()"); }  public static void main(String[] args) {    PrivateOverride po = new Derived();    po.f();  }}class Derived extends PrivateOverride {  public void f() { print("public f()"); }} /* Output:private f()
  • 只有普通的方法调用可以是多态的。域(变量)和静态的方法也不具有多态性质。
class Super {  public int field = 0;  public int getField() { return field; }}class Sub extends Super {  public int field = 1;  public int getField() { return field; }  public int getSuperField() { return super.field; }}public class FieldAccess {  public static void main(String[] args) {    Super sup = new Sub(); // Upcast    System.out.println("sup.field = " + sup.field +      ", sup.getField() = " + sup.getField());    Sub sub = new Sub();    System.out.println("sub.field = " +      sub.field + ", sub.getField() = " +      sub.getField() +      ", sub.getSuperField() = " +      sub.getSuperField());  }} /* Output:sup.field = 0, sup.getField() = 1sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0*///:~

构造器和多态

  • 对于导出类的构造器,在第一行必须调用 基类 的构造器,否则编译器会报错。当然,如果基类有无参的构造器,则可以不用显式的调用,因为编译器会帮助我们隐式调用。
    • 首先将分配给对象的空间初始化为二进制的0
    • 按声明顺序调用成员的初始化方法
    • 然后调用该类的构造器
  • 根据以上规则,当我们手动写dispose()方法的时候,我们销毁的顺序应该是和初始化的顺序是相反的,因为这样可以避免某个子类对象依赖其他的对象。
  • 如果遇到类之间有共享变量的情况,那么销毁的顺序就变得复杂了,一般采用计数器的方法,记录着引用的个数。
  • 在构造器内唯一安全调用的那些方法是final方法,也适用于private方法,因为他们自动属于final方法。

协变返回类型

  • 协变返回类型就是如果方法要求返回一个对象,则我们可以返回这个对象的子类。

向下转型

  • 向上转型我们会丢失具体的类型信息
  • 在java中,所有的转型都会得到检查。这种运行期间对类型进行检查的行为称作“运行时的类型识别”。

参考

  • http://blog.csdn.net/seu_calvin/article/details/52191321(建议看)
  • http://www.cnblogs.com/loveincode/p/7230448.html(建议看)
  • http://www.runoob.com/java/java-override-overload.html
原创粉丝点击