第九章 接口和抽象類 接口詳解

1.完全解耦

  • 一個方法 void next(Processor p),如果p僅僅是一個父類 或抽象類的話,那傳入這個方法的p只能是繼承暈Processor的子類或Processor類,
    其他的類則不能傳入,而如果是Processor是一個接口的話那傳入其中的類只要實現這個接口就可以啦,這個類就可以留出空間去繼承其他
    的類了,也可以去實現其他接口,這個方法的耦合性就低了很多。
  • 讓方法接受接口類型,是一種讓任何類對該方法進行適配的方式,只要這個類implement這個接口。

2.java中的多重繼承

  • java是單繼承語言,但可以通過藉口的方式實現多重繼承。
    因爲接口根本沒有任何具體實現,也就是說沒有任何與接口相關的存儲,
  • 實現接口和繼承的不同之處,
    繼承 子類需要在構造方法中先調用父類構造方法完成父類的初始化,因爲子類中可能有依賴父類的方法。
    接口不用,因爲子類一點點都沒有依賴所實現的接口,這也是接口爲什麼能實現多重繼承的一個原因。
  • interface CanFight{
    	void fight();
    }
    interface CanSwim{
    	void swim();
    }
    interface CanFly{
    	void fly();
    }
    class ActionCharacter{
    	public void fight(){}
    }
    
    class Hero extends ActionCharacter
    	implements CanFight,CanFly,CanSwim{
    	public void swim() {}
    	public void fly() {}
    	/**
    	 * 下面這句代碼註釋掉也沒關係,雖然我們implement了CanFight,但因爲父類中有這個方法,所以不需要實現。
    	 * 即使沒有顯示的定義fight()方法,其定義也會隨着父類而來
    	 */
    //	public void fight(){}
    }
    
    public class Adventure {
    }
    
  • 當使用Hero時,他會被以此向上轉型爲相應的接口類型。

3.通過繼承來擴展接口(接口繼承接口)

  • 接口繼承接口,可以實現接口的擴展。
  • 當一個類實現了一個繼承接口的接口的時候,那這個類必須實現所有接口的方法
    另外接口繼承接口也用extends關鍵字,但extends後面可以跟多個接口,用逗號隔開。
    interface CanDos extends CanFly,CanSwim{
    	void dos();
    }
    class ActionCharacter implements CanDos{
    	public void fight(){}
    	public void fly() {}
    	public void swim() {}
    	public void dos() {}
    }
    

4.組合接口時的方法名字的衝突

  • 當打算組合的接口中使用相同的名字會造成代碼的可讀性的混亂,雖然運行不會出什麼問題,儘量避免這種情況。
    interface I1{
        void f();
    }
    interface I2{
        void f();
    }
    interface I3 extends I2{
        void f();
    }
    
    class C1 implements I3,I2{
        public void f() {}
    }
    
    public class Test extends C1{
    
        public void f() {System.out.println("呵呵");}
        public static void main(String[] args) {
            C1 i = new Test();
            i.f();
        }
    }
    
    
    


5.接口相當於枚舉

  • 因爲在接口中的域都是final、static和public的(public final static int i = 0;),所以在java沒有枚舉之前接口可以當作其來達到相同的作用。
    因爲接口中的域都是final的所以必須對它們初始化。
    interface RandVal{
    	Random RAND = new Random(47);
    	int RANDOM_INT = RAND.nextInt(10);
    	long RANDOM_LONG = RAND.nextInt()*10;
    }
    public class TestRandVals {
    	public static void main(String[] args) {
    		System.out.println(RandVal.RANDOM_INT);
    		System.out.println(RandVal.RANDOM_LONG);
    	}
    }
  • 這些域不是接口的一部分,他們的值存儲在該接口的靜態存儲區域內。

6.嵌套接口

  • 接口可以嵌套在類或其他接口中。
  • class A{
    	interface B{
    		void f();
    	}
    	public class BImp implements B{
    		public void f() {}
    	}
    	private class BImp2 implements B{
    		public void f() {}
    	}
    	//private類型的
    	private interface D{
    		void f();
    	}
    	private class DImp implements D{
    		public void f() {}
    	}
    	public class DImp2 implements D{
    		public void f() {}
    	}
    }
    
    interface E{
    	interface G{
    		void f();
    	}
    	public interface H{
    		void f();
    	}
    	void g();
    }
    
    public class NestingInterfaces {
    }
    上面的代碼有一處特出的情況,就是接口在類內部被聲明爲private修飾的時候。
    這只是一種方法,因爲是private的,它會強制不允許向上轉型。
  • 當實現某個接口時,並不需要實現嵌套在其內部的任何接口,繼承類也一樣。

7.接口和工廠

  • 可以通過接口實現工廠模式,使用工廠對戲那個生成接口的某個實現對象。使用設計模式應該考慮到自身的情況,選擇適合的設計模式。
    但也有情況是不能使用模式的。

總結:

  • 繼承和接口不能濫用,考慮情況而定,可以直接實現類的時候優先實現類。



發佈了26 篇原創文章 · 獲贊 14 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章