《Java 编程思想》第8章 多态 笔记
2017-01-24 12:08
218 查看
第8章 多态
一,向上转型由导出类转型为基类,在继承图上是向上移动,因此一般称为向上转型。换句话说,把导出类类对象直接赋给基类引用叫upcasting向上转型。
package other; enum Note{ MIDDLE_C,C_SHARP,B_FLAT; } class Instrument{ public void play(Note n){ System.out.println("Instrument play()"); } @Override public String toString() { return "Instrument!"; } } class Wind extends Instrument{ @Override public String toString() { // TODO Auto-generated method stub return "Wind!"; } @Override public void play(Note n) { System.out.println("Wind play()"+n); } public void Sound(){ System.out.println("Wind Sound()!"); } } class Brass extends Instrument{ @Override public String toString() { // TODO Auto-generated method stub return "Brass!"; } @Override public void play(Note n) { System.out.println("Brass play()"+n); } public void Sound(){ System.out.println("Brass Sound()!"); } } public class Music { public static void tune(Instrument i){ i.play(Note.MIDDLE_C); } public static void main(String[] args) { Instrument b=new Brass(); Instrument w=new Wind(); System.out.println(b); w.play(Note.C_SHARP); tune(b); ((Wind) b).Sound(); } }
输出结果:
Brass!
Wind play()C_SHARP
Brass play()MIDDLE_C
向上转型:
Instrument b=new Brass();
Instrument w=new Wind();
System.out.println(b);调用Brass的toString(),输出Brass!
w.play(Note.C_SHARP);调用Wind的play(),输出Wind play()C_SHARP
向上转型的好处:
public static void tune(Instrument i);
这里以基类引用为参数,调有时用导出类引用作为参数,就是利用了向上转型。这样使代码变得简洁。不然的话,就要为每一个导出类都编写一个新的tune(),这也体现了JAVA的抽象编程思想。
当然,导出类向上转型到基类可能会“缩小”接口,但不会比基类的全部接口更窄。需要注意的是向上转型时会遗失除与父类对象共有的其他方法。如本例中的Sound()方法不再为b所有。
((Wind) b).Sound();这时会提示进行类型的显性转换,但是转换不成功,抛出java.lang.ClassCastException异常。
二,方法调用绑定
将一个方法调用和一个方法主体关联起来称作绑定,若程序在执行前进行绑定(由编译器和连接程序实现),叫做前期绑定,比如static方法和final方法(private方法属于final方法)。在运行时根据对象的类型进行绑定称为后期绑定,也叫做动态绑定。后期绑定也解决了编辑器只有一个基类引用时,究竟该调用哪个方法的问题。
public static void tune(Instrument i){ i.play(Note.MIDDLE_C); }
Instrument引用对play()的调用都是通过后期绑定进行的。
通过这样,tune()方法可以忽略周围代码所发生的变化,依旧正常运行,换句话说:多态是一项将改变的事物和未变的事物分离开来的技术。
但是其中也存在一些问题要注意,以下都不具有多态性;
1,private方法
package other; class Dervied extends PrivateOverride{ public void f(){ System.out.println("public f()"); } } public class PrivateOverride { private void f(){ System.out.println("private f()"); } public static void main(String[] args) { PrivateOverride p=new Dervied();//向上转型 p.f(); } }
输出是private f(),只有非private方法才可以被重载覆盖,基类中的f()对于子类Derived是不可见的,所以也无法进行重载。在导出类中,对于基类中的private方法,最好采用不同的命名。
2,类中的域不具有多态性
class Super{ public int field=1; public int getField(){ return field; } } class Sub extends Super{ public int field=2; public int getField(){ return field; } } public class Test7 { public static void main(String[] args) { Super sub=new Sub();//向上转型 System.out.println("sub.field="+sub.field+","+"sub.getfield()="+sub.getField()); } }
输出结果:sub.field=1,sub.getfield()=2,类中的域是在运行前就解析赋初值了。因此Super和Sub中的field分别分配不同的存储空间。他们各不相干,但是在实际中,这个问题也不太会发生,首先,类中的域都被设置成private,不能直接访问,可以调用方法访问,其次,基类和导出类的域命名都是不同的
3,静态方法,它的行为就不具有多态性,因为static在运行前就已经被绑定。
相关文章推荐
- [学习笔记][Java编程思想]第8章:多态
- java 编程思想笔记之多态
- Java编程思想:第8章 多态
- java编程思想笔记08-多态
- Java 编程思想(第四版)学习笔记(8)多态
- java 编程思想笔记之多态
- java编程思想笔记(第四版*第8章)
- java编程思想笔记--多态部分二
- 【学习笔记】JAva编程思想之多态
- 【笔记】Java编程思想—一多态
- Java编程思想_第八章_多态笔记
- Java编程思想学习笔记_2(继承和多态)
- 【Java编程思想笔记】第八章-多态
- java编程思想学习-第8章多态
- java编程思想笔记--多态部分五
- Java编程思想笔记第八章(多态)
- java编程思想笔记--多态部分四
- java编程思想笔记--多态部分一
- (28)21.3.2 解决共享资源竞争---Java编程思想之并发笔记
- Java 编程思想(第四版)学习笔记(7)复用类