Thinking In Java Part05(抽象)

1、抽象類和抽象方法
	如果我們只提供接口,但沒有具體的實現內容,創建這個對象是沒有什麼意義的,而且我們可能還想要阻止使用者這麼做。通過讓這個對象的所有方法報錯可以實現阻止創建這個對象的目的。但是這樣做會將錯誤信息延遲到運行時才獲得,並且要在客戶端進行可靠、詳盡的測試。所以最好在編譯時捕獲這些問題。也就是儘可能不創建無內容的接口或者說對象。
	爲此,Java提供了一個叫做抽象方法的機制,這種方法是不完整的,僅有聲明而沒有方法體。語法:
		abstract void f();
	包含抽象方法的類叫做抽象類。如果一個類包含一個或多個抽象方法,該類必須被限定爲抽象的(否則,編譯器會報錯)
	如果一個抽象類不完整,那麼當我們視圖產生該類的對象時,編譯器會由於爲抽象類創建對象不完全而報錯。這樣,編譯器會確保抽象類的純粹性,我們不必擔心誤用。
	如果從一個抽象類繼承,並想創建該新類的對象,那麼就必須爲基類中的所有抽象方法提供方法定義。如果不這樣做(可以選擇不做),那麼導出類便也是抽象類,且編譯器將會強制我們用abstrace關鍵字來限定這個類。
	我們也可能會創建一個沒有任何抽象方法的抽象類。這個類包含任何abstract方法都顯得沒有實際意義,而且我也想要阻止產生這個類的任何對象,那麼這樣做就有用了。
2、接口
	interface關鍵字使抽象的概念更向前邁進了一步。abstract關鍵字允許人們在類中創建一個或多個沒有任何定義的方法——提供了接口部分,但是沒有提供任何相應的具體實現,這些實現由此類的繼承者創建的。interface這個關鍵字產生一個完全抽象的類,根本沒有提供任何具體的實現。它允許創建者確定方法名、參數列表和返回類型,但是沒有任何方法體。接口只提供了形式,而未提供任何具體實現。
	一個接口表示:“所有實現了該特定接口的類看起來都像這樣”。因此,任何使用某特定接口的代碼都知道可以調用該接口的哪些方法,而且僅需要知道這些。因此,接口被用來建立類與類之間的協議。(某些面向對象編程語言使用protocol關鍵詞來完成)
	interface不僅僅是一個極度抽象的類,因爲它允許人們通過創建一個能夠被向上轉型爲多種基類的類型,來實現某種類似多重繼變種的特性。
	如果不再interface前添加public關鍵字,則它只有包訪問權限,只能在同一個包內可用。接口也可以包含域,但是這些域隱式地是static和final的。
3、策略設計模式
	調用方中的一個方法可以接受一個基類,然和根據這個基類的超類具有不同的行爲。也就是創建一個能夠根據鎖傳遞的參數對象的不同而具有不同行爲的方法,被稱爲策略設計模式。
4、使用接口的核心原因
	爲了能夠向上轉型爲多個基類型(以及由此而帶來的靈活性)。然而,使用接口的第二個原因卻是與使用抽象基類相同:防止客戶端程序員創建該類的對象,並確保這僅僅是建立一個接口。這就會有一個問題:我們到底應該使用接口還是抽象類?如果要創建不帶任何方法定義和成員變量的基類,那麼應該選擇接口而不是抽象類。事實上,如果知道某事物應該成爲一個基類,那麼第一選擇應該是使它成爲一個接口。
5、嵌套接口
	接口可以嵌套在類或其他接口中
	接口也可以被實現爲private,可以被實現爲public,但是隻能被其自身所使用。也就是說實現一個private接口只是一種方式,它可以強制該接口中的方法定義不要添加任何類型信息(也就是說,不允許向上轉型)。
	接口彼此之間也可以嵌套。但是所有的接口元素都必須是public,而且在另一個接口中的接口自動是public 的,而不能聲明爲private。
	當實現某個接口時,並不需要實現嵌套在其內部的任何接口。而且,private不能在定義它的類之外被實現。
6、接口和工廠
	接口是實現多重繼承的途徑,而生成遵循某個接口的典型方式就是工廠方法設計模式。這與直接調用構造器不同,我們在工廠對象上調用的是創建方法,而該工廠對象將生成接口的某個實現的對象。理論上,通過這種方式,我們的代碼將完全與接口的實現分離,這就使得我們可以透明地將某個實現替換爲另一個實現。
7、內部類
	可以將一個類的定義放在另一個類的定義內部,就是內部類。
	爲什麼內部類自動擁有對外圍類所有成員的訪問權?
		當某個外圍類的對象創建了一個內部類對象時,此內部類對象必定會祕密地捕獲一個指向那個外圍類對象的引用。然後在你訪問此外圍類的成員時,就是用那個引用來選擇外圍類的成員。編譯器會幫我們處理所有的細節。內部類的對只能在其外圍類的對象相關聯的情況下才能被創建(內部類非static類時)。構建內部類對象時,需要一個執行其外圍類對象的引用,如果編譯器訪問不到這個引用就會報錯。
			public Selector selector() {
		        return new InnerSelector();
		    }
		    會自動被編譯成 
		    public Selector selector() {
		        return new Inner.InnerSelector();
		    }
8、在方法和作用域內的內部類
	8.1、爲什麼在一個方法裏面或者在任意的作用域內定義內部類:
		8.1.1、實現了某類型的接口,於是可以創建並返回對其的引用。
		8.1.2、要解決一個複雜的問題,想創建一個類來輔助你的解決方案,但是又不希望這個類是公共可用的。
	8.2、在方法的作用於內的(而不是在其他類的作用於內)創建一個完整的類。叫做局部內部類
		PDestination是destination()方法的一部分,而不是PartInner的一部分。所以在destination()之外不能訪問PDestination。return語句進行了向上轉型——返回的是destination的引用,爲PDestination的基類。
9、嵌套類
	如果不需要內部類對象與其外圍類對象之間的關係,那麼可以將內部類聲明爲static。這通常被稱爲嵌套類。普通的內部類鍍錫隱式地保存了一個引用,指向創建它的外圍類對象。當內部類時staic時,嵌套類意味着:
		要創建嵌套類的對象,並不需要其外圍類的對象。
		不能從嵌套類的對象中訪問非靜態的外圍類對象。
	普通的內部類的字段與方法,只能放在類的外部層次上,所以普通的內部類不能有static數據和staitic字段,也不能包含嵌套類。但是嵌套類可以包含它們。
	在一個普通的(非staitic)內部類中,通過一個特殊的this引用可以連接到其外圍類對象。嵌套類沒有這個特殊的this引用,這使得它類似一個static方法。
10、接口內部的類
	正常情況下,不能在接口內部放置任何代碼,但嵌套類可以作爲接口的一部分。你放到接口中的任何類都自動地是public和static的。因爲類時static,只是將嵌套類置於接口的命名空間內,這並不違反接口的規則,甚至可以在內部類中實現其外圍接口。
	如果想要創建某些公共代碼,使得它們可以被某個接口的所有不同實現所公用,那麼使用接口內部的嵌套類就很方便。也可以用嵌套類來放測試代碼。

工廠模式 只是根據Factory返回不同的對象,不需要自己加配置

interface Service {
    void method1();

    void method2();
}

interface ServiceFactory {
    Service getService();
}

class Imple1 implements Service {

    @Override
    public void method1() {
        System.out.println("Imple1method1");
    }

    @Override
    public void method2() {
        System.out.println("Imple1method1");
    }
}

class ImpleFact1 implements ServiceFactory {

    @Override
    public Service getService() {
        return new Imple1();
    }
}

class Imple2 implements Service {

    @Override
    public void method1() {
        System.out.println("Imple2method1");
    }

    @Override
    public void method2() {
        System.out.println("Imple2method1");
    }
}

class ImpleFact2 implements ServiceFactory {

    @Override
    public Service getService() {
        return new Imple2();
    }
}

public class Factories {
    static void serviceConsu(ServiceFactory fact) {
        Service service = fact.getService();
        service.method1();
        service.method2();
    }

    public static void main(String[] args) {
        serviceConsu(new ImpleFact1());
        serviceConsu(new ImpleFact2());
    }
}

內部類對外圍類的所有成員有訪問權

    public class Inner {
    private Object[] items;
    private int next = 0;

    public Inner(int size) {
        this.items = new Object[size];
    }

    public void add(Object x) {
        if (this.next < this.items.length) {
            this.items[this.next++] = x;
        }

    }

    public Selector selector() {
        return new Inner.InnerSelector();
    }

    public static void main(String[] args) {
        Inner inner = new Inner(10);

        for(int i = 0; i < 10; ++i) {
            inner.add(Integer.toString(i));
        }

        Selector selector = inner.selector();

        while(!selector.end()) {
            System.out.println(selector.current() + "");
            selector.next();
        }

    }

    private class InnerSelector implements Selector {
        private int i;

        private InnerSelector() {
            this.i = 0;
        }

        public boolean end() {
            return this.i == Inner.this.items.length;
        }

        public Object current() {
            return Inner.this.items[this.i];
        }

        public void next() {
            if (this.i < Inner.this.items.length) {
                ++this.i;
            }

        }
    }
}

局部內部類

interface Destination {
    String readLabel();
}

public class PartInner {
    public Destination destination(String s){
        class PDestination implements Destination{
            private String label;
            private PDestination(String label){
                this.label = label;
            }
            @Override
            public String readLabel() {
                return label;
            }
        }
        return new PDestination(s);
    }


    public static void main(String[] args){
        PartInner partInner = new PartInner();
        Destination eeeee = partInner.destination("eeeee");
        System.out.println(eeeee.readLabel());
    }
}

接口內部類

interface a {
	    void run();

	    class b implements a {
	        @Override
	        public void run() {
	            System.out.println("hhh");
	        }

	        public static void main(String[] args) {
	            new b().run();
	        }
	    }
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章