Java编程思想多态笔记

来源:互联网 发布:依斯莉8杯水套淘宝真假 编辑:程序博客网 时间:2024/06/05 21:00

多态

多态分离了做什么和怎么做,从另外一个角度将接口和实现分离开了。

方法调用绑定

将一个方法调用和一个方法主体关联起来被称之为绑定。如果在程序执行之前进行绑定(编译器和连接程序实现),叫做前期绑定。而在运行时根据对象的类型进行绑定叫做后期绑定(也叫动态绑定或运行时绑定)。编译器是不知道对象的具体类型的,但是方法调用机制能找到正确的方法体进行调用。而这种机制的实现依赖于在对象中安置“类型信息”。

在Java里面除了static和final方法以外,都是后期绑定。方法声明为final与其说是禁止别人覆写该方法,还不如说是关闭了动态绑定。

域和静态方法里面的多态

对于静态方法由于是和类对象相关联的,并不是和单个对象相关联,所以不会产生多态。
如果直接访问某个域,这个访问会将在编译器进行解析。例如:

public class FieldAccess {    public static void main(String[] args) {        Super sup = new Sub();        // 在编译器就直接拿到了域里面的值,而调用方法会产生多态        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());    }}class Super {    public int field = 0;    public int getField() {        return field;    }}class Sub extends Super {    // 这里的Sub对象其实含有两个field域,所以必须显式    // 使用Super.field才能访问父类的域    public int field = 1;    public int getField() {        return field;    }    public int  getSuperField() {        return super.field;    }}/*output:sup.field = 0, sup.getField() = 1sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0*/

构造器和多态

实际上构造器是static方法,不过是隐式的声明,并不具有多态性。

对于一个复杂对象调用构造器会遵循下面的顺序:

  1. 调用父类的构造器,一直向上
  2. 按照声明顺序调用成员的初始化方法,如果没有创建对象就没有
  3. 调用该类构造器主体

协变返回类型

在子类的重写方法中可以返回父类方法的返回类型的某种导出类型(子类)

继承设计通用准则

使用继承来表达行为间的差异,并用字段表达状态上的变化,字段使用组合。即包含的字段指向一个父类,通过改变这个引用指向不同的子类对象来改变组合对象的行为模式。代码如下:

public class InheritanceDesign {    public static void main(String[] args) {        EA aEa = new EA();        aEa.func2();        aEa.change(new B());        aEa.func2();    }}class A {    void func() {System.out.println("A");}}class B extends A {    @Override    void func() {System.out.println("B");}}class C extends A {    @Override    void func() {System.out.println("C");}}class D extends A {    @Override    void func() {System.out.println("D");}}class EA {    // 组合    A a = new A();    // 改变父类的指向,传入不同的子类对象    // 从而实现行为的变化    void change(A a) {        this.a = a;    }    void func2() {        a.func();    }}

向下转型和运行时类型识别

向上转型–丢失类型信息(安全,基于is-a)
向下转型–获取类型信息(不安全,父类不知道实际指向的是哪种子类对象)
基于上文,Java在进行类型转换的时候会有一个“运行时类型识别(RTTI)”机制。

0 0