一,、很多人在初次接觸設(shè)計模式的時候,,最大的疑惑莫過于碰到這樣的句子:(父類Animal和子類Dog)Animal a2 = new Dog(); 這是什么玩意兒?究竟有什么用途,,我直接用子類對象不就完了,? 二、這種用法叫做“父類引用指向子類對象”(跟繞口令似的),,或者叫“父類指針指向子類對象”,,指的是定義一個父類的引用,而它實際指向的是子類創(chuàng)建的對象,。功能上相當(dāng)于子類的“向上轉(zhuǎn)型”,,或者“上溯對象”。 Animal a2 = new Animal(); Dog dog = new Dog(); a2 = dog; 將子類對象賦給父類的引用就是向上轉(zhuǎn)型,,Animal a2 = new Dog();中的new Dog()就是實例化一個沒有名字的對象,,然后轉(zhuǎn)型給父類的引用a2,僅此而已,。 三,、一般來說,一個對象實例創(chuàng)建完就定死了,,比如dog,,如果程序里的變量寫dog的話,萬一以后發(fā)生變化就要改代碼了,。那么事先就不寫死dog,,而是寫父類Animal,那么以后用到Animal的地方,用dog實例,cat實例都可以取代,,不用改實例名了,。說玄乎一點,也就體現(xiàn)了面向?qū)ο蟆岸鄳B(tài)”的特性,。 下面看一個很簡單的例子,,就更加明白了: class Animal { private String type = "Animal"; public virtual void showLegs() { Console.WriteLine("This is an {0} , Animal always has legs",type); } } class Dog : Animal { private String type = "Dog"; public override void showLegs() { Console.WriteLine("This is a {0} , Dog has four legs", type); } } class Glede : Animal { private String type = "Glede"; public override void showLegs() { Console.WriteLine("This is a {0} , Glede has two legs",type); } } class test { static void Main(string[] args) { Animal a1 = new Animal(); Animal a2 = new Dog(); Animal a3 = new Glede(); a1.showLegs(); a2.showLegs(); a3.showLegs(); Console.ReadLine(); } } 結(jié)果: This is an Animal , Animal always has legs This is a Dog , Dog has four legs This is a Glede , Glede has two legs 真正明白了這些,也就該接觸設(shè)計模式領(lǐng)域了,。 (1)·因為a2,a3都是子類的對象,,所以調(diào)用起來,也都是調(diào)用的子類的方法(當(dāng)然前提是它們都override了父類方法,諸位可以試著把兩個子類中的override替換成new,,結(jié)果就完全不一樣,,具體查看override與new的區(qū)別),有人把這叫做“關(guān)注對象原則”,。 (2)·向上轉(zhuǎn)型是一定沒有錯的,,就好比你說“狗是動物”是成立的,反之,,向下轉(zhuǎn)型就要注意了,,你不能說“動物是狗”。 四,、父類引用指向子類對象的理解: (1)例如父類Animal,,子類Cat,Dog。其中Animal可以是類也可以是接口,,Cat和Dog是繼承或?qū)崿F(xiàn)Animal的子類,。 Animal animal = new Cat(); 即聲明的是父類,實際指向的是子類的一個對象,。那這么使用的優(yōu)點是什么,,為什么要這么用? (2)可以用這幾個關(guān)鍵詞來概括:多態(tài),、動態(tài)鏈接,,向上轉(zhuǎn)型 也有人說這是面向接口編程,可以降低程序的耦合性,,即調(diào)用者不必關(guān)心調(diào)用的是哪個對象,,只需要針對接口編程就可以了,被調(diào)用者對于調(diào)用者是完全透明的,。讓你更關(guān)注父類能做什么,而不去關(guān)心子類是具體怎么做的,你可以隨時替換一個子類,也就是隨時替換一個具體實現(xiàn),而不用修改其他. 以后結(jié)合設(shè)計模式(如工廠模式,,代理模式)和反射機制可能有更深理解。 下面介紹java的多態(tài)性和其中的動態(tài)鏈接,,向上轉(zhuǎn)型: (3)面向?qū)ο蟮娜齻€特征:封裝,、繼承和多態(tài); 封裝隱藏了類的內(nèi)部實現(xiàn)機制,,可以在不影響使用者的前提下修改類的內(nèi)部結(jié)構(gòu),,同時保護了數(shù)據(jù); 繼承是為了重用父類代碼,,子類繼承父類就擁有了父類的成員,。 方法的重寫、重載與動態(tài)連接構(gòu)成多態(tài)性,。Java之所以引入多態(tài)的概念,,原因之一是它在類的繼承問題上和C++不同,,后者允許多繼承,,這確實給其帶來的非常強大的功能,,但是復(fù)雜的繼承關(guān)系也給C++開發(fā)者帶來了更大的麻煩,為了規(guī)避風(fēng)險,,Java只允許單繼承,,派生類與基類間有IS-A的關(guān)系(即“貓”is a “動物”)。這樣做雖然保證了繼承關(guān)系的簡單明了,,但是勢必在功能上有很大的限制,,所以,Java引入了多態(tài)性的概念以彌補這點的不足,,此外,,抽象類和接口也是解決單繼承規(guī)定限制的重要手段。同時,,多態(tài)也是面向?qū)ο缶幊痰木杷凇?nbsp; (4)理解多態(tài),,首先要知道“向上轉(zhuǎn)型”。 我定義了一個子類Cat,,它繼承了Animal類,,那么后者就是前者是父類。我可以通過 那么這樣做有什么意義呢,?因為子類是對父類的一個改進和擴充,,所以一般子類在功能上較父類更強大,屬性較父類更獨特,, 定義一個父類類型的引用指向一個子類的對象既可以使用子類強大的功能,,又可以抽取父類的共性。 所以,,父類類型的引用可以調(diào)用父類中定義的所有屬性和方法,,而對于子類中定義而父類中沒有的方法,父類引用是無法調(diào)用的,; 當(dāng)父類中的一個方法只有在父類中定義而在子類中沒有重寫的情況下,,才可以被父類類型的引用調(diào)用; 對于父類中定義的方法,,如果子類中重寫了該方法,,那么父類類型的引用將會調(diào)用子類中的這個方法,這就是動態(tài)連接,。 下面看一下典型的多態(tài)例子: 1. class Father{ 2. public void func1(){ 3. func2(); 4. } 5. //這是父類中的func2()方法,,因為下面的子類中重寫(又稱:覆寫)了該方法 6. //所以在父類類型的引用中調(diào)用時,這個方法將不再有效 7. //取而代之的是將調(diào)用子類中重寫的func2()方法 8. public void func2(){ 9. System.out.println("AAA"); 10. } 11. } 12. 13. class Child extends Father{ 14. //func1(int i)是對func1()方法的一個重載,,主要不是重寫,! 15. //由于在父類中沒有定義這個方法,所以它不能被父類類型的引用調(diào)用 16. //所以在下面的main方法中child.func1(68)是不對的 17. public void func1(int i){ 18. System.out.println("BBB"); 19. } 20. //func2()重寫了父類Father中的func2()方法 21. //如果父類類型的引用中調(diào)用了func2()方法,,那么必然是子類中重寫的這個方法 22. public void func2(){ 23. System.out.println("CCC"); 24. } 25. } 26. 27. public class PolymorphismTest { 28. public static void main(String[] args) { 29. Father child = new Child(); 30. child.func1();//打印結(jié)果將會是什么,? 31. child.func1(68); 32. } 33. } 上面的程序是個很典型的多態(tài)的例子。子類Child繼承了父類Father,,并重載了父類的func1()方法,,重寫了父類的func2()方法。重載后的func1(int i)和func1()不再是同一個方法,,由于父類中沒有func1(int i),,那么,父類類型的引用child就不能調(diào)用func1(int i)方法,。而子類重寫了func2()方法,,那么父類類型的引用child在調(diào)用該方法時將會調(diào)用子類中重寫的func2()。 五,、 對于多態(tài),,可以總結(jié)以下幾點: (1)、使用父類類型的引用指向子類的對象,; |
|
來自: 一生有你__ > 《基礎(chǔ)知識》