java物件類型轉換和多態性,java對象轉換多態

來源:互聯網
上載者:User

java物件類型轉換和多態性,java對象轉換多態
物件類型轉換

分為向上轉型和向下轉型(強制對象轉型)。 向上轉型是子物件向父物件轉型的過程,例如貓類轉換為動物類;向下轉型是強制轉型實現的,是父物件強制轉換為子物件。 這和基礎資料類型的轉換是類似的,byte在需要時會自動轉換為int(向上轉型),int可以強制轉型為byte(向下轉型)。

對於對象轉型來說, 向上轉型後子物件專屬的成員將不可訪問 。 意思是,在需要一隻動物時,可以把貓當作一隻動物傳遞,因為貓繼承自動物,貓具有動物的所有屬性。但向上轉型後,貓不再是貓,而是被當作動物看待,它自己專屬的屬性和方法就不可見了。換句話說,向上轉型後,只能識別父物件中的內容。

可以通過"引用變數 instanceof 類名"的方式來判斷引用變數 所指向的對象 是否屬於某個類,也就是說"對象是不是某類",例如聲明一個貓類對象的引用"Cat c",然後"c instanceof Animal"表述的意思是"對象c是一種動物嗎?"對於instanceof返回true的對象,都可以轉換為類對象,只不過有些可能需要強制轉換。

向上轉型可以自動進行,這本就是符合邏輯的,狗類繼承自動物類,它本身就是一隻動物,因此在需要動物類的時候,丟一隻狗過去就會自動向上轉型成動物類。但這時狗已經不是狗,而是動物,所以狗專屬的成員不再可見。

強制轉換的方式和基礎資料類型強制轉換一樣,都是在待轉換對象前加上目標類型,例如將動物a強制轉換為狗d: Dog d = (Dog)a 。

下面是一個物件類型轉換的樣本,很好地分析了能否轉型、轉型後能否訪問某些成員等等。

class Animal {    String name;    Animal(String name) {this.name = name;}}class Cat extends Animal {    String eyecolor;    Cat(String name,String color) {super(name); this.eyecolor = color;}}class Dog extends Animal {    String furcolor;    Dog(String name,String color) {super(name); this.furcolor = color;}}public class OCast {    public static void main(String [] args) {        Animal a = new Animal("animal");        Cat c = new Cat("cat","blue");        Dog d = new Dog("dog","black");        System.out.println( a instanceof Animal);//return true        System.out.println( c instanceof Animal);//return true        System.out.println( d instanceof Animal);//return true        System.out.println( a instanceof Cat);   //return false        System.out.println(a.name); //return animal        a = new Dog("yellowdog","yellow");       //object Dog upcast to Animal        System.out.println(a.name);              //return yellowdog        System.out.println(a instanceof Animal); //return true        System.out.println(a instanceof Dog);    //return true        //System.out.println(a.furcolor);        //error! because a was regarded as Animal        Dog d1 = (Dog)a;     // because "a instanceof Dog" is true,so force cast Animal a to Dog        System.out.println(d1.furcolor);         //return yellow    }}

對於上面的 a = new Dog("yellowdog",yellow) ,a是Animal類型,但此時 它指向的是Dog對象。也就是說它是Dog,所以也是Animal類 ,所以 a instanceof Animal); 和 a instanceof Dog; 都是true,這是它的"指標"決定的。 但因為它的類型是Animal類型,類型決定了能儲存什麼樣的資料,對於已經存在的但不符合類型的資料都是不可見的,所以Animal類型決定了它只能看到Dog對象中的Animal部分 。如:

既然可以向上轉型,配合instanceof的邏輯判斷,就能實現很好的擴充性。例如,動物類的sing(Animal a)方法需要的是一個動物類,可以給它一隻狗d,這時會向上轉型(就像需要double類型卻給了一個int資料一樣),雖然轉型了,但狗d的實際引用仍然是Dog對象,於是 if (a instanceof Dog) 判斷為真,則調用能體現狗sing()方法特殊性的語句。如果傳遞一隻貓,if判斷一下並調用能體現貓sing()方法特殊性的語句。這樣,任何時候想添加一隻動物,都只需要增加一條if語句就可以了。見下面的樣本:

class Animal {    String name;    Animal(String name) {        this.name = name;    }}class Cat extends Animal {Cat(String name) {super(name);}}class Dog extends Animal {Dog(String name) {super(name);}}public class TestCast {    public static void main(String [] args) {        TestCast t = new TestCast();         Animal a = new Animal("animal");        Animal c = new Cat("cat");        Animal d = new Dog("dog");        t.sing(a);t.sing(c);t.sing(d);    }    void sing(Animal a) {        if ( a instanceof Cat) {            Cat cat = (Cat)a;            System.out.println("cat is singing");        } else if(a instanceof Dog) {            Dog dog = (Dog)a;            System.out.println("dog is singing");        } else {            System.out.println("not an instance of animal");        }    }}

如果沒有對象轉型,那麼Dog裡要定義一次sing(),Cat裡也要定義一次sing()。要增加一個動物類,動物類裡也還要定義一次sing()。現在就方便多了,直接在sing()方法內部修改if語句就可以了。

注意,上面的sing()方法不屬於Animal或其他子類的方法,而是獨立定義在其他類裡進行調用的。

多態

向上轉型雖然在一定程度上提高了可擴充性,但提高的程度並不太高。以向上轉型為基礎,java的多態實現的擴充性更好更方便。

多態也叫動態綁定或後期綁定,它是執行期間進行的綁定,而非編譯期間的綁定(這是靜態繫結或稱為前期綁定)。

多態的原理是:當向上轉型後,調用一個被重寫的方法時,本該調用的是父類方法,但實際上卻會動態地調用子類重寫後的方法。實際上,編譯期間綁定的確實是父類方法,只不過在執行期間動態轉調子類對應方法。

例如,Animal類的sing()方法,Cat和Dog類都重寫了sing()方法。當需要一個Animal對象時,傳遞了一個Cat類,那麼將調用Cat的sing()方法。動態綁定的邏輯正如下面的代碼類似:

void sing(Animal a) {    if ( a instanceof Cat) {        Cat cat = (Cat)a;        System.out.println("cat is singing");    } else if(a instanceof Dog) {        Dog dog = (Dog)a;        System.out.println("dog is singing");    } else {        System.out.println("not an instance of animal");    }}

以下是一個多態的例子:

class Animal {  private String name;  Animal(String name) {this.name = name;}  public void sing(){System.out.println("animal sing...");}}class Cat extends Animal {  private String eyeColor;  Cat(String n,String c) {super(n); eyeColor = c;}  public void sing() {System.out.println("cat sing...");}}class Dog extends Animal {    private String furColor;    Dog(String n,String c) {super(n); furColor = c;}    public void sing() {System.out.println("dog sing...");}}class Lady {    private String name;    private Animal pet;    Lady(String name,Animal pet) {this.name = name; this.pet = pet;}    public void myPetSing(){pet.sing();}}public class DuoTai {    public static void main(String args[]){        Cat c = new Cat("catname","blue");        Dog d = new Dog("dogname","black");        Lady l1 = new Lady("l1",c);        Lady l2 = new Lady("l2",d);        l1.myPetSing();        l2.myPetSing();    }}

編譯後的執行結果為:

cat sing...dog sing...

在上面的樣本中,Lady類的構造方法和她調用sing()方法的代碼為:

Lady(String name,Animal pet) {this.name = name; this.pet = pet;}public void myPetSing(){pet.sing();}

如果構造出Lady對象的pet是Cat對象c,這個c首先會向上轉型為Animal類,也就是說Lady的pet屬性雖然指向的是"Cat c"對象,但它只能看見其中的父物件Animal部分。那麼 myPetSing(pet.sing();) 方法自然會調用Animal類的sing()方法。 以上過程是編譯器所認為的過程,也是靜態繫結或前期綁定的過程。

但編譯完成後,雖然pet屬性只能看見Animal部分,但實際在執行時pet.sing()卻換轉換為執行c.sing()。就相當於做了一次物件類型強制轉換 Cat petx = (Cat)pet 。 這是動態綁定或後期綁定的過程,也稱為多態。

實際上,對象在被new出來後,它所涉及到的方法都放在code segment記憶體區中的一個方法列表中,這個列表中包含了子類、父類的方法,只不過有些時候不可見的方法無法去調用。當執行程式時,內部的機制可以從方法列表中搜尋出最符合環境的方法並執行它。

實現多態的技術的關鍵點在於:

  • (1). 定義一個父類引用f,並將其指向子類對象,即進行向上轉型 ;
  • (2). 重寫父類的方法,並使用父類引用f去引用這個方法。這樣就可以面向父類進行編程 。

正如上面的樣本中,將pet定義為Animal類而非具體的子類,並在方法中調用pet.sing()。如此依賴,就無需考慮pet到底是Cat/Dog,在進行功能擴充添加Bird類時,完全不用再修改Lady類的這段代碼。

再例如,父類Animal,子類Dog,方法sing()。

class Animal {public void sing(A);}class Dog extends Animal {public void sing(B);}public class Test {    Animal a = new Dog();  //父類引用變數a指向子物件Dog,此時將向上轉型    a.sing();              //使用父類引用變數a引用被重寫的方法sing(),執行時將動態綁定到Dog的sing()}


歡迎加入學習交流群569772982,大家一起學習交流。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.