1. 程式人生 > >易學筆記--從0開始學JAVA(個人純手工筆記共享 免費!免費!免費!)--第8章 多型

易學筆記--從0開始學JAVA(個人純手工筆記共享 免費!免費!免費!)--第8章 多型

  1. 向上引用本質:物件引用為基類型別,實際為匯出類型別
    1. 原始碼例子:
      1. 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);
        	}
        
        }
        
      2. package mypackage.music;
        
        import mypackage.music.*;
        import static mypackage.Print.*;
        
        public class Instrument {
          public void play(Note n) {
        	print("Instrument.paly");
         }
        }
        
      3. package mypackage.music;
        
        import mypackage.music.*;
        import static mypackage.Print.*;
        
        public class Wind extends Instrument {
        	public void play(Note n) {
               print("wind.play:" + n);
        	}
        }
        
      4. package mypackage.music;
        
        public enum Note {
           MiDDLE_C,C_SHARP,B_FLAT;
        }
        
    2. 輸出結果:
    • 舉例:
    • 動態繫結的例子
      1. 原始碼:
        1. 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();
          		}
          	}
          
          }
          
        2. package mypackage.shape;
          
          import mypackage.Print;
          
          public class Shape {
          	public void draw() {
          		Print.print("Shape.dram");
          	}
          
          	public void erase() {
          		Print.print("Shape.erase");
          	}
          }
          
        3. package mypackage.shape;
          
          import static mypackage.Print.*;
          
          public class Circle extends Shape {
               public void draw() {
          		print("Circle.draw");
          	}
               public void erase() {
          		print("Circle.erase");
          	}
          }
          
        4. 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");
          	}
          }
        5. 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");
          	}
          }
          
      2. 輸出結果:
  1. 這時候再往 類中加入更多方法,同時匯出類也新增通用的方法,沒關係,這個方法依舊可以使用,並且不用修改不用編譯
  2. 擴充套件後的類為:
    • 例子
      1. 原始碼:
        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());
        	}
        
        }
        
      2. 輸出結果:
  • 靜態方法
  1. 儘管靜態方法是public的,但是也不是多型的
  2. 例子
    1. 原始碼:
    2. 輸出結果:
  1. 組合、繼承、多型性構造順序例子
    1. 原始碼:
      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();
      	}
      
      }
      
    2. 輸出結果:
  1. 舉例子:
    1. 原始碼:
      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();
      	}
      
      }
      
    2. 結果輸出:
    • 舉例:
      1. 原始碼:,因為呼叫順序為:
        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);
        	}
        
        }
        
      2. 輸出結果:
    • 結論
      1. 構造器應該足夠簡單,只進行初始化成員域即可,儘量不要呼叫方法
      2. 如果要呼叫方法也是呼叫final方法或者private方法,因為這些方法不會被覆蓋

  1. 前期繫結還是後期繫結:第8章 多型/8.2 轉機/8.2.1 方法呼叫繫結
    1. 對於C語言,沒有方法過載,所以所有的C語言都是前期繫結的;
    2. 對於Java,除了final和static方法,都是動態繫結的
    3. 因為final方法只能在本類使用,static方法只能屬性宣告類或者匯出類類名呼叫。
    4. 如果是向上轉型物件呼叫static方法,那麼呼叫的都是物件宣告型別對應的方法(通常就是基類的方法)
  2. 域是不能多型的,也就是基類和匯出類的域是分開儲存的
  3. 如果多型發生在基類構造方法中,那呼叫的方法是匯出類的,但是匯出類的初始化在基類後面,那該方法有可能用了未初始化的變數,那是非常危險的