Java编程思想多态笔记

多态

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

方法调用绑定

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

在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() = 1
sub.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值