Chapter 8 Polymorphism

  1. Overview

看到書中的例子我以爲我都懂了,不過看到了一個例子之後,才發現我都是半懂,沒有仔細思考,看書的時候心不靜。關於多態有一個優先級可以概括,詳見http://blog.csdn.net/thinkghoster/archive/2008/04/19/2307001.aspx。優先級由高到低依次爲:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

  1. Example and research

 

class A {
         
public String show(D obj){
                
return ("A and D");
         } 
         
public String show(A obj){
                
return ("A and A");
         } 

class B extends A{
         
public String show(B obj){
                
return ("B and B");
         }
         
public String show(A obj){
                
return ("B and A");
         } 
}
class C extends B{} 
class D extends B{} 

以下是結果

        A a1 = new A();
        A a2 = 
new B();
        B b = 
new B();
        C c = 
new C(); 
        D d = 
new D(); 
        System.out.println(a1.show(b));  

        System.out.println(a1.show(c));  

        System.out.println(a1.show(d));  

        
System.out.println(a2.show(b));  
        System.out.println(a2.show(c));  

        System.out.println(a2.show(d));  

        System.out.println(b.show(b));    
        System.out.println(b.show(c));     

        
System.out.println(b.show(d));        

 

其中4,5,6,9全部做錯。那就一個一個驗證這個優先級吧。

  1. System.out.println(a2.show(b))

    之前看過書中有這樣的例子:

import java.util.*;

 

class Shape {

void draw() {System.out.println("Shape.draw()");}

void erase() {}

}

 

class Circle extends Shape {

void draw() {

System.out.println("Circle.draw()");

}

void erase() {

System.out.println("Circle.erase()");

}

}

 

class Square extends Shape {

void draw() {

System.out.println("Square.draw()");

}

void erase() {

System.out.println("Square.erase()");

}

}

 

class Triangle extends Shape {

void draw() {

System.out.println("Triangle.draw()");

}

void erase() {

System.out.println("Triangle.erase()");

}

}

 

// A "factory" that randomly creates shapes:

class RandomShapeGenerator {

private Random rand = new Random();

public Shape next() {

switch(rand.nextInt(3)) {

default:

case 0: return new Circle();

case 1: return new Square();

case 2: return new Triangle();

}

}

}

 

public class Shapes {

private static RandomShapeGenerator gen =

new RandomShapeGenerator();

public static void main(String[] args) {

Shape[] s = new Shape[9];

// Fill up the array with shapes:

for(int i = 0; i < s.length; i++)

s[i] = gen.next();

// Make polymorphic method calls:

for(int i = 0; i < s.length; i++){

s[i].draw();

};

}

}

 

結果如下:

Square.draw()

Circle.draw()

Triangle.draw()

Triangle.draw()

Triangle.draw()

Circle.draw()

Square.draw()

Triangle.draw()

Circle.draw()

每一個父類Shape引用的都是子類,輸出的也都是子類的方法。所以我以爲對於4中應該輸出"B AND B"。但是注意到調用的方法在父類中一個在父類中定義過了,一個沒有。什麼意思?如果在類A中加上這麼一段:

public String show(B obj){

return ("A and BB");

}

那麼4的結果就是"B AND B"。這是類A和B中都有一個同樣的方法show(B obj)。那爲什麼4的結果是"B AND A"了?注意到剛纔說的優先級,首先查找this.show(),這是是沒有對應的方法的。接着查找super.show(),super.show是沒有的,因爲a2的定義是A a2 = new B(),a2還是一個類型爲a的引用變量。接着查找this.show((super)O),這樣就找到了對應的方法了,爲類A中的show(A object)方法,但是注意子類B中有方法把他給覆蓋了!所以使用的類B中的方法!結果爲"B and A"

其他的都同理可以論證了。

  1. My thinking in java

    加上了多態後,立刻變的複雜了。從面向過程轉到面向對象我還非常不習慣,習慣於參數必須和聲明的參數類型完全一樣。有了多態和抽象類到底有什麼好處,爲什麼要引入這兩個東西了?

  • 抽象類

    我覺得抽象類主要是提高代碼的可讀性,如果沒有抽象類也一樣可以實現這樣的功能。比如在父類中的方法實現就寫爲空,然後在子類中覆蓋就行了,加上了abstract之後只不過加上了語法的檢查。

  • 多態和繼承

    多態是一個利器,不過很有可能讓代碼變的更糟糕。父類和子類有三種情況:

  1. 父類方法比子類多

    這種情況下公共的接口最好用abstract,父類中多出來的方法,作爲所有子類的公共方法使用設置爲Public讓子類繼承。

  2. 父類方法和子類一樣多

    這個時候最好父類的方法都用來繼承,提供公共的接口。

  3. 父類方法少於子類

    相同的部分作爲公共接口,子類中多出來的方法可以用downcasting。

    這樣定義類時都可以用父類的引用使用子類方法。

    

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章