第八章 多态 多态的优点与作用 和缺陷

来源:互联网 发布:html是不是编程语言 编辑:程序博客网 时间:2024/06/15 12:25

1.可扩展性

  • 多态是一项让程序员“将改变的事物和未变的事物分离开来的重要技术”。
    改变的事物可能是添加了新的子类或父类和子类添加了新的方法,未变的事物可能是对基类的调用如 tune(Instrument i)方法调用,传入i的可能是个子类,而且可能会不断继承而产生新的子类
    但都不能影响这个方法,这个方法完全忽略周围的改变,这就是改变的事物和未变的事物分离开来。
  • 一个良好的OOP系统都遵循tune(Instrument i)的模型【Instrument是一个父类】,而且只与父类(Instrument)接口通讯。
    这样的程序时可扩展的,因为可以继承父类【Instrument】扩展出新的子类来,从而添加一些现有子类没有的功能、方法。
    class Instrument{void play(Note n){System.out.println("Instrument.play()" + n);}String what(){return "Instrument";}void adjust(){System.out.println("Adjusting Instrument");}}class Wind extends Instrument{void play(Note n){System.out.println("Wind.play()" + n);}String what(){return "Wind";}void adjust(){System.out.println("Adjusting Wind");}}class Percussion extends Instrument{void play(Note n){System.out.println("Percussion.play()" + n);}String what(){return "Percussion";}void adjust(){System.out.println("Adjusting Percussion");}}..........省略的代码public class Music {//可以看到形式参数时以根父类,无论子类怎样扩展都不会影响这个tune方法public static void tune(Instrument i){i.play(Note.MIDDLE_C);}public static void tuneAll(Instrument[] e){for(Instrument i : e)tune(i);}public static void main(String[] args) {Instrument[] orchestra = {new Wind(),new Percussion(),new Stringed(),new Brass(),new Woodwind()};tuneAll(orchestra);}}

2.缺陷1,覆盖 私有方法

  • public class PrivateOverride {private void f(){System.out.println("private f()");}public static void main(String[] args) {//向上转型,会丢失子类中的方法PrivateOverride po = new Derived();po.f();}}class Derived extends PrivateOverride{public void f(){System.out.println("public f()");}}//输出private f()

    看上面的方法的输出我们期望的是输出Derived中的public f(),但是并没有,
    因为涉及向上转型,java会查找子类中重写的父类方法,如果有重写就执行子类重写的方法,没有,就执行父类的方法,
    在这个例子中,父类的f方法是私有的,不可能被重写,也就是说子类并没有重写,子类中的f只是他的新方法而已,有时向上转型,那就执行父类中的方法了。
  • 反过来可不可以,更不可以啦,反过来是子类没有重写f方法,因为他是private的。是子类私有的新方法。

3.缺陷2 域和静态方法

  • 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 sub = new Sub();System.out.println(sub.field + sub.getField());Sub sub2 = new Sub();System.out.println(sub2.getSuperField());}}

    看这段代码,任何域访问操作都是有编译器解析,也就是前期绑定,因此不是多态
    Super.field 和 Sub.field分配了不同的存储空间。
  • sub实际上包含了两个称为field的域,它自己的和从父类中得到的。
  • 引用中的field所产生的默认域并非Super版本的field域,要引用父类中的域,就是用super关键字吧。
  • 另外,如果某个方法是静态的,它的行为也不具有多态性


0 0
原创粉丝点击