易學筆記--從0開始學JAVA(個人純手工筆記共享 免費!免費!免費!)--第8章 多型
阿新 • • 發佈:2018-12-19
- 向上引用本質:物件引用為基類型別,實際為匯出類型別
- 原始碼例子:
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Music { public static void tune(Instrument i) { i.play(Note.MiDDLE_C); } public static void main(String[] args) { // TODO Auto-generated method stub Wind fluteWind = new Wind(); tune(fluteWind); } }
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Instrument { public void play(Note n) { print("Instrument.paly"); } }
-
package mypackage.music; import mypackage.music.*; import static mypackage.Print.*; public class Wind extends Instrument { public void play(Note n) { print("wind.play:" + n); } }
-
package mypackage.music; public enum Note { MiDDLE_C,C_SHARP,B_FLAT; }
-
- 輸出結果:
- 原始碼例子:
-
- 舉例:
- 動態繫結的例子
- 原始碼:
-
package mypackage.shape; import java.util.Iterator; public class Shapes { private static RandomShape randomShape = new RandomShape(); public static void main(String[] args) { // TODO Auto-generated method stub Shape[] shape = new Shape[9]; for (int i = 0; i < shape.length; i++) { shape[i] = randomShape.next(); } for (Shape shape2 : shape) { shape2.draw(); // shape2.erase(); } } }
-
package mypackage.shape; import mypackage.Print; public class Shape { public void draw() { Print.print("Shape.dram"); } public void erase() { Print.print("Shape.erase"); } }
-
package mypackage.shape; import static mypackage.Print.*; public class Circle extends Shape { public void draw() { print("Circle.draw"); } public void erase() { print("Circle.erase"); } }
-
package mypackage.shape; import static mypackage.Print.print; public class Square extends Shape { public void draw() { print("Square.draw"); } public void erase() { print("Square.erase"); } }
-
package mypackage.shape; import java.util.Random; import mypackage.Print; public class RandomShape { private Random random = new Random(47); public Shape next() { int value = random.nextInt(3); // Print.print("value = " + value); switch (value) { case 0: return new Circle(); case 1: return new Shape(); case 2: return new Triangle(); default: return new Shape(); } } }
package mypackage.shape; import static mypackage.Print.print; public class Triangle extends Shape { public void draw() { print("Triangle.draw"); } public void erase() { print("Triangle.erase"); } }
-
- 輸出結果:
- 原始碼:
- 這時候再往 類中加入更多方法,同時匯出類也新增通用的方法,沒關係,這個方法依舊可以使用,並且不用修改不用編譯
- 擴充套件後的類為:
-
- 例子
- 原始碼:
import mypackage.Print; class Super{ public int field = 0; public int getField(){ return field; } } class Sub extends Super{ public int field = 1; public int getField(){ return field; } public int getSuperField() { return super.field; } } public class FieldAccess { public static void main(String[] args) { // TODO Auto-generated method stub Super super1 = new Sub(); Print.print("super1.field = " + super1.field + ",super1.getField = " + super1.getField()); Sub sub = new Sub(); Print.print("sub.field = " + sub.field + ",sub.getField = " + sub.getField()); } }
- 輸出結果:
- 原始碼:
- 例子
- 靜態方法
- 儘管靜態方法是public的,但是也不是多型的
- 例子
- 原始碼:
- 輸出結果:
- 組合、繼承、多型性構造順序例子
- 原始碼:
package polymorphism; import static mypackage.Print.*; class Meal { Meal() { print("Meal"); } } class Bread { Bread() { print("Bread"); } } class Cheese { Cheese() { print("Cheese"); } } class Letytuce { Letytuce() { print("Letytuce"); } } class Lunch extends Meal{ Lunch() { print("Lunch"); } } class PortableLunch extends Lunch{ PortableLunch() { print("PortableLunch"); } } public class Sandwich extends PortableLunch{ private Bread bread = new Bread(); private Cheese cheese = new Cheese(); private Letytuce letytuce = new Letytuce(); public Sandwich(){ print("Sandwich"); } public static void main(String[] args) { // TODO Auto-generated method stub new Sandwich(); } }
- 輸出結果:
- 原始碼:
- 舉例子:
- 原始碼:
package polymorphism; import static mypackage.Print.*; class Characteristic{ //Characteristic:特徵/特點 private String s; Characteristic(String s){ this.s = s; print("Characteristic:" + s); } protected void dispost() { print("dispost:" + s); } } class Description{ //Description:描述 private String s; Description(String s){ this.s = s; print("Description:" + s); } protected void dispost() { print("Description:" + s); } } class LivingCreature{ //LivingCreature:生物 private Characteristic pCharacteristic = new Characteristic("is alive"); private Description pDescription = new Description("Basic Living Creature"); LivingCreature(){ print("LivingCreature"); } protected void dispost() { print("LivingCreature dispost" ); pDescription.dispost(); pCharacteristic.dispost(); } } class Animal extends LivingCreature{ private Characteristic pCharacteristic = new Characteristic("has heart"); private Description pDescription = new Description("Animal not vegetable"); Animal(){ print("Animal"); } protected void dispost() { print("Animal dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } } class Amphibian extends Animal{ //兩棲動物 private Characteristic pCharacteristic = new Characteristic("can live in water"); private Description pDescription = new Description("both water and land"); Amphibian(){ print("Amphibian"); } protected void dispost() { print("Amphibian dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } } public class Forg extends Amphibian{//青蛙 private Characteristic pCharacteristic = new Characteristic("Croaks"); private Description pDescription = new Description("Eats Bugs"); public Forg(){ print("Forg"); } protected void dispost() { print("Forg dispost" ); pDescription.dispost(); pCharacteristic.dispost(); super.dispost(); } public static void main(String[] args) { // TODO Auto-generated method stub Forg forg = new Forg(); print("bye"); forg.dispost(); } }
- 結果輸出:
- 原始碼:
-
- 舉例:
- 原始碼:,因為呼叫順序為:
package polymorphism; import static mypackage.Print.*; class Glyph { //圖象字元 void draw(){ print("Glyph draw"); } Glyph(){ print("Glyph before"); draw(); print("Glyph after"); } } class RoundGlyph extends Glyph{ //圓形符號 private int radius = 1; RoundGlyph(int r){ radius = r; print("RoundGlyph radius = " + radius); } void draw(){ print("RoundGlyph radius = " + radius); } } public class PolyConstructors { public static void main(String[] args) { // TODO Auto-generated method stub new RoundGlyph(5); } }
- 輸出結果:
- 原始碼:,因為呼叫順序為:
- 結論
- 構造器應該足夠簡單,只進行初始化成員域即可,儘量不要呼叫方法
- 如果要呼叫方法也是呼叫final方法或者private方法,因為這些方法不會被覆蓋
- 舉例:
- 前期繫結還是後期繫結:第8章 多型/8.2 轉機/8.2.1 方法呼叫繫結
- 對於C語言,沒有方法過載,所以所有的C語言都是前期繫結的;
- 對於Java,除了final和static方法,都是動態繫結的
- 因為final方法只能在本類使用,static方法只能屬性宣告類或者匯出類類名呼叫。
- 如果是向上轉型物件呼叫static方法,那麼呼叫的都是物件宣告型別對應的方法(通常就是基類的方法)
- 域是不能多型的,也就是基類和匯出類的域是分開儲存的
- 如果多型發生在基類構造方法中,那呼叫的方法是匯出類的,但是匯出類的初始化在基類後面,那該方法有可能用了未初始化的變數,那是非常危險的