Thinking In Java 4th Chap8 多态(未完)

多态的意义:改善代码的可读性并且使得程序“可扩展”

多态方法调用允许一种类型表现出与其他相似类型之间的"区别",基于方法的行为不同而表现出来

将一个方法调用同一个方法主体关联起来称作绑定,程序执行前绑定称为前期绑定,运行时根据对象的类型进行绑定称为后期绑定

  Java中除了static和final(包括private)方法,都采用后期绑定。

向上转型可以表现为此语句:(在调用方法时总是会进行正确的调用,也即调用正确的子类的方法)

  (Shape类是Circle类的基类)Shape s = new Circle();

   调用方法:s.draw();(draw()方法已经在Circle类中被覆写)实际上调用的还是Circle.draw(),虽然对象s被声明为Shape(但是指向Circle类的引用)

 1 package Music;
 2 enum Note{
 3     MIDDLE_C,C_SHARP,B_FLAT
 4 }
 5 class Instrument{
 6     void play(Note n) {
 7         System.out.print("Instrument.play()" + n);
 8     }
 9 };
10 class Percussion extends Instrument{
11     void play(Note n) {
12         System.out.print("Percussion.play()" + n);
13     }
14 };
15 class Stringed extends Instrument{
16     void play(Note n) {
17         System.out.print("Stringed.play()" + n);
18     }
19 };
20 class Wind extends Instrument{
21     void play(Note n) {
22         System.out.print("Wind.play()" + n);
23     }
24 };
25 class Music4{
26     static void tune(Instrument i){
27         i.play(Note.MIDDLE_C);
28     }
29     static void tuneAll(Instrument[] e){
30         for(Instrument i:e){
31             tune(i);
32         }
33     }
34     public static void main(String[]args){
35         Instrument[]orchestra={
36                 new Wind(),
37                 new Percussion(),
38                 new Stringed(),
39         };
40         tuneAll(orchestra);
41     }
42 };

上述“向上引用”的缺陷是:如果覆写了private方法,那么“向上引用”的结果是调用基类的private方法

 只有普通的方法的调用可以是多态的,如果直接访问某个域,那么访问就在编译期解析:

 1 class Super{
 2     public int field=0;
 3     public int getField(){
 4         return field;
 5     }
 6 }
 7 class Sub extends Super{
 8     public int field=1;
 9     public int getField(){
10         return field;
11     }
12     public int getSuperField(){
13         return super.field;
14     }
15 }
16 class FieldAccess{
17     public static void main(String []args){
18         Super sup=new Sub();//upcasting
19         System.out.println("sup.field="+sup.field+",sup.getfield()="+sup.getField());
20         Sub sub=new Sub();
21         System.out.println("sub.field="+sub.field+",sub.getfield()="+sub.getField()+",sub.getSuperField()="+sub.getSuperField());
22 
23     }
24 }/**output:
25  sup.field=0,sup.getfield()=1
26  sub.field=1,sub.getfield()=1,sub.getSuperField()=0*/

如果某个方法是静态的,则不具备多态性:

 1 class StaticSuper{
 2     public static String staticGet(){
 3         return "Base staticGet()";
 4     }
 5     public String dynamicGet(){
 6         return "Base dynamicGet()";
 7     }
 8 }
 9 class StaticSub extends StaticSuper{
10     public static String staticGet(){
11         return "Sub staticGet()";
12     }
13     public String dynamicGet(){
14         return "Sub dynamicGet()";
15     }
16 }
17 class StaticPolymorphism{
18     public static void main(String[]args){
19         StaticSuper sup=new StaticSub();
20         System.out.println("sup.staticGet()="+sup.staticGet());
21         System.out.println("sup.dynamicGet()="+sup.dynamicGet());
22     }
23 }
24 /**output:
25  * sup.staticGet()=Base staticGet()
26  * sup.dynamicGet()=Sub dynamicGet()*/

构造器和多态(构造器隐式的声明为static)

构造器的调用顺序实例:

 1 class Meal{
 2     Meal(){
 3         System.out.print("Meal()");
 4     }
 5 }
 6 class Bread{
 7     Bread(){
 8         System.out.print("Bread()");
 9     }
10 }
11 class Cheese{
12     Cheese(){
13         System.out.print("Cheese()");
14     }
15 }
16 class Lettuce{
17     Lettuce(){
18         System.out.print("Lettuce()");
19     }
20 }
21 class Lunch extends Meal{
22     Lunch(){
23         System.out.print("Lunch()");
24     }
25 }
26 class PortableLunch extends Lunch{
27     PortableLunch(){
28         System.out.print("PortableLunch()");
29     }
30 }
31 class Sandwich extends PortableLunch{
32     private Bread b = new Bread();
33     private Cheese c= new Cheese();
34     private Lettuce l = new Lettuce();
35     Sandwich(){
36         System.out.print("Sandwich()");
37     }
38     public static void main(String[]args){
39        new Sandwich();
40     }
41 }
42 /**output:
43  * Meal()Lunch()PortableLunch()Bread()Cheese()Lettuce()Sandwich()*/

可见构造器的调用顺序:基类构造器->组合方法调用成员构造器->继承类构造器(自己)

继承和清理:

 

posted @ 2019-09-15 14:49  Dragonsburg  阅读(176)  评论(0编辑  收藏  举报