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关键字吧。
- 另外,如果某个方法是静态的,它的行为也不具有多态性。