国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

抽象類和接口

2019-11-08 01:51:38
字體:
來源:轉載
供稿:網友

抽象類

當描述一批對象的時候,我們通常會將一些共有的方法和屬性進行向上抽取,抽取出它們的父類,通過繼承達到代碼復用的目的。

但是,每個子類的方法某些方法業務都是獨一無二的,它們都重寫了父類中定義的該方法。而這個時候,父類就沒有必要提供該方法的具體實現了,只需要將該方法定義為抽象方法,而且該類的存在也僅僅是為了讓子類繼承,實現代碼的復用,那么我們就可以將該類定義為抽象類。

抽象類必須使用abstract修飾符來修飾類名,有抽象方法的類只能被定義成抽象類,抽象類里可以沒有抽象方法,也可以有具體實現的方法。

規則:

1、  抽象類必須使用abstract修飾符來修飾類,抽象方法也必須使用abstract來修飾,抽象方法不能有方法體。

2、  抽象類不能被實例化,不能使用new關鍵字來調用抽象類的構造器創建抽象類的實例。即使抽象類里不包含抽象方法,也不能被創建實例。

3、  抽象類可以包含成員變量、方法(普通方法和抽象方法都可以)、構造器、初始化塊、內部類5種成分。抽象類的構造器不能用來創建實例,主要是用于被其子類調用。

abstract class Fu{    publicFu(String str){        System.out.PRintln(str);    }}class Zi1 extends Fu{    publicZi1(){        super("abcd");    }}

4、含有抽象方法的類只能被定義為抽象類。

 

定義抽象方法只需要在普通方法上增加abstract修飾符,并且把方法體去掉,在后面加分號即可。

注意:抽象方法和空方法完全不是同一個概念。一個是抽象方法,一個是普通方法,只不過普通方法沒有具體代碼。

 

定義抽象類

只需要在普通類上增加abstract修飾符即可。甚至一個普通類(沒有抽象方法)增加abstract修飾符后也將變成抽象類。

//定義Shape抽象類和實現類三角形,圓形求周長方法。獲取形狀方法

class AbstractTest{    //使用抽象類,進行解耦操作    static XingZhuang xz;    public static void main(String[] args){        if(true){            xz= new Circle(12.12 ,"紅色");        }else{            xz= new Rect(12,12,"黑色");        }        double zc= xz.zhouChang();        String info = xz.getInfo();    }}abstract class XingZhuang //形狀{    abstract double zhouChang();    abstract String getInfo();    String color;   } class Circle extends XingZhuang{    public Circle(double radius , String color){        this.radius= radius;        this.color= color;    }           double radius;    double zc= 0;    double zhouChang(){        zc =Math.PI * 2 * radius;        return zc;    }    String getInfo(){        return color + "圓形的周長是:"+ zc;    }}class Rect extends XingZhuang{    double chang;    double kuang;    double zc= 0;    public Rect(double chang ,  double kuang,String color){        this.chang= chang;        this.kuang= kuang;        this.color= color;    }     double zhouChang(){         zc = (chang + kuang) * 2;        return zc;     }     String getInfo(){            return color + "矩形的周長是:"+ zc;     }}

 

抽象類的作用

抽象類不能被創建實例,只能當成父類被繼承。普通類描述對象是對某一類事物的抽象,而抽象類則是更高層次的抽象。從多個具有相同特征的類中抽象出一個抽象類,以這個抽象類作為其子類的模板,從而避免了子類設計的隨意性。

抽象類體現的就是一種模板的設計,抽象類作為多個子類的模板,子類建立在抽象類的基礎上進行擴展,改造,但子類總體上大致會保留這些抽象類的行為。

如果編寫一個抽象類,父類可以提供多個子類通用的抽象方法,并把具體實現推遲到子類去實現。當然,父類也可以提供通用的普通方法,這些普通方法可以作為輔助方法用來輔助子類。

 

接口

抽象類是從多個類中抽象出來的模板,如果將這種抽象進行的更加徹底,則可以提煉出一種更加特殊的抽象類--接口(interface),接口里不能包含普通方法,接口里所有的方法都是抽象方法。

接口的概念:

在計算機主板上,有N多個接口插槽,供我們拓展計算機的功能,如顯卡、內存、硬盤、聲卡等。主板只是定義了一下接口規則,這些生產顯卡、內存等廠家生產的產品必須實現該接口的規則,才可以將它們的產品插到主板上。

那么,在java中,接口就是定義了一種規范,接口定義的某一批類所需要遵守的規范,接口并不關心這些類的內部狀態數據,也不關心這些類里的方法實現的細節,它只是規定了這批類里必須提供某些方法,提供這些方法的類就可以滿足實際需要。

可見,接口是從多個類中抽象出來的規范,接口不提供任何實現。接口體現的是規范和實現分離的設計哲學。

class JieKou{    public static void main(String[] args){        DianNao dn = new DianNao();        //調用方法,傳入實現Input接口的實現類        dn.getInput(new JianPan());               //調用方法,傳入實現Input接口的實現類        dn.getInput(new ShouXie());    }}

 class DianNao{    //定義了獲取信息需要的組件,只需要遵循Input接口就OK    void getInput(Input input){        System.out.println("輸入了" + input. inputMethod());    }}

//定義了輸入設備的規范

interface Input{    String inputMethod();}//遵循了輸入設備的規范的鍵盤class JianPan implements Input{        publicString inputMethod(){            return"鍵盤";        }}//遵循了輸入設備的規范的手寫板class ShouXie implements Input{        public String input Method(){            return "手寫";        }} 

 

 

 

讓規范和實現分離正是接口的好處,弱化了各個組件之間的依賴性,即松耦合設計。例如主機上的各種插槽,只要顯卡遵守規范,就可以與主機進行通信,至于顯卡是如何設計,內部怎么實現,主板無需關心。

類似的,軟件系統之間的各個模塊之間也應該采用這種面向接口的耦合,從而降低各個模塊之間的耦合,為系統提供了更好的可擴展性和可維護性。

因此,接口定義的是多個類共同的公共行為的規范,這些行為是與外部交流的通道,這就意味著接口里通常是定義一組公用方法。

定義規則:

interface 接口名 extends 父接口1、父接口2

{

         0到多個抽象方法的定義

         0到多個內部類、接口、枚舉

         0到多個默認方法或類方法

}

詳細說明:

1、命名規范與類名一致。大駝峰。

2、接口可以有多個直接父接口,但是接口只能繼承接口,不可以繼承類。

由于接口定義的是一種規范,因此接口里不能包含構造器和初始化塊。接口可以包含成員變量(只能是靜態常量)、方法(只能是抽象實例方法、類方法或默認方法)、內部類(包括內部接口、枚舉)定義。

對比接口和類的定義方式,不難發現接口的成員比類里的成員少了兩種,而且接口里的成員變量只能是靜態常量,接口里的方法只能是抽象方法。

class JieKou{    public static void main(String[] args){        DaoDian daoDian = new DaoDianImpl();        String[] cusInfo = daoDian.cusInfo();        String mrs = daoDian.mrs(cusInfo[0]);        System.out.println(mrs);        daoDian.zhixing(mrs, cusInfo[1]);    }}

 

//顧客到店服務

interface DaoDian{    //獲取預約顧客的信息    String[] cusInfo();    //安排顧客預約的美容師    String mrs(String name);    //執行預約的服務    void zhixing(String name , String fuwu);}class DaoDianImpl implements DaoDian{    //獲取預約顧客的信息    public String[] cusInfo(){String[] arr = new String[]{"顧客小紅" , "Spa"};        retur narr;    }    //安排顧客預約的美容師    public String mrs(String name){        if(name.equals("顧客小紅")){               return "小蘭";        }        return "小明";    }    //執行預約的服務    public  void zhixing(String name , String fuwu){        System.out.println(name+"美容師執行了" +fuwu+"項目");    }}

前面已經說了,接口里定義的是多個類共同的公共行為規范,因此接口里的所有成員,包括常量、方法、內部類都是public訪問權限。定義接口成員時,可以省略訪問控制修飾符,如果指定訪問控制修飾符,則只能使用public訪問控制修飾符。

對于接口里的定義的靜態常量而言,他們是接口相關的,因此系統會自動為這些成員變量增加static和final兩個修飾符。也就是說,在接口中定義成員變量時,不管是否使用public static final修飾符,接口里的成員變量總是使用者3個修飾符來修飾,而且接口里沒有構造器和初始化塊,因此接口里定義的成員變量只能是在定義時指定默認值。

如下兩行代碼的結果是完全一樣的。

int MAX_SIZE = 50;

public static final int MAX_SIZE = 50;

接口里定義的方法只能是抽象方法,因此系統會將自動為普通方法增加public abstract修飾符。

1、  屬性一律使用靜態修飾符:

如下,接口中定義屬性沒有使用static修飾,但是在測試類中,直接使用接口.name就可以訪問該屬性,說明該屬性是靜態的。

         屬性權限修飾符是:public

如下,屬性是默認修飾符,但是在不同包下的類中,也可以訪問。

屬性默認使用final修飾:

2、  方法默認使用abstract、public

在接口中定義方法,使用默認權限修飾,子類也使用默認權限修飾,報錯,說接口的該方法是public,證明了,接口方法默認使用public修飾。

 

接口的繼承:

接口的繼承和類的繼承不一樣,接口是完全支持多繼承的,即一個接口可以有多個直接父接口。和類繼承想死,接口擴展某個父接口,將會獲得負借口定義的所有抽象方法、常量。

一個接口繼承多個父接口時,多個父接口排在extends關鍵字之后,多個父接口之間以英文逗號隔開。

//TODOclass JieKou implements JieKouC,JieKouB,JieKouA{    public void methodc(){}    public void methodb(){}    public void methoda(){}}interface JieKouA{    void methoda();}interface JieKouB{       void methodb();}interface JieKouC{       void methodc();} 

接口的多層繼承,實現接口,如果接口還有父類接口,那么實現類必須實現包括接口和其父接口的所有抽象方法:

class JieKou implements JieKouC{    public void methodc(){}    public void methodb(){}    public void methoda(){}}interface JieKouA{    void methoda();}interface JieKouB extends JieKouA{       void methodb();}interface JieKouC extends JieKouB{       void methodc();}

使用接口

接口不能用于創建實例,但接口可以用于聲明引用類型變量。當使用接口來聲明引用類型變量時,這個引用類型變量必須引用到其實現類的對象,這也是屬于多態特性。

class JieKou{    public static void main(String[]  args){        Person person = new Man();    }}interface Person{ }class Man implements Person{}

 

接口的主要用途就是被實現類實現,除此之外,,接口主要用途如下:

1、  定義變量,也可以用于進行強制類型轉換。

class JieKou{    public static void main(String[] args){        Manman = new Man();        Person person = (Person)man;    }}

2、  調用接口中定義的常量。

3、被其他類實現,實現功能的擴展

一個類可以實現一個或多個接口,繼承只能使用extends關鍵字實現單繼承,實現接口使用implements關鍵字多實現。

//TODOclass JieKou{    public static void main(String[] args){        Man man = new Man();        Person person = (Person)man;    }}class Person{ }class Man extends Person implements Working,ShanYang{    void zhengqian(){}    void xiwan(){}    void shanYang(){}}class WoMan extends Person implements ShanYang{    void shanYang(){}}interface Working{    void zhengqian();    void xiwan();}interface ShanYang{    void shanYang();}

實現接口與繼承父類相似,一樣可以獲得所實現接口里定義的常量(成員變量)、方法(包括抽象方法和默認方法)

 

讓類實現接口需要定義后增加implements部分,當需要實現多個接口時,使用逗號隔開,一個類可以繼承一個父類,并且同時實現多個接口。implements必須放在extends之后。

一個類實現一個或多個接口后,這個類必須實現這些接口里所定義的全部抽象方法(也就是重寫),否則就定義為抽象類。

一個類實現某個接口,就會擁有該接口的定義的常量、方法等。因此也可以將實現接口理解為一種特殊的繼承。相當于一個更加徹底的抽象類。

//TODO實現兩個接口,兩個接口都可以接受該對象

class JieKou{    public static void main(String[] args){        Working working =  new Man();        ShanYang shanYang = (ShanYang)working;    }}class Person{ }class Man extends Person implements Working,ShanYang{    public void zhengqian(){}    public void xiwan(){}    public void shanYang(){}} interface Working{    void zhengqian();    void xiwan();}interface ShanYang{    void shanYang();}

接口不能繼承任何類,但是所有接口類型的變量都可以直接賦值給Object類型的引用變量。因為既然是存在的對象,那么肯定是Object對象的子類對象。

class JieKou{    public static void main(String[] args){        Working working =  new Man();        Object obj =working;    }}

接口和抽象類區別

接口和抽象類很相似,都具有如下特征:

1、接口和抽象類都不能被實例化,他們都需要被繼承或實現。

2、接口和抽象類都可以包含抽象方法,實現或繼承他們的普通類必須重寫抽象方法。

但接口和抽象差別也是非常大,這種差別主要體現在二者的設計目的上。

接口作為系統與外界的交互的窗口,接口體現的是一種規范,對于接口的實現者而言,接口規定了實現者必須向外提供哪些服務,對于接口調用者而言,接口規定了調用者可以調用哪些服務,以及如何調用。當一個程序中使用了接口時,接口是多個模塊間的耦合標準。當多個程序之間使用了接口,那么該接口就是多個程序之間的通訊標準。

抽象類則不一樣,抽象類作為多個子類共同父類,他所體現的是一種模板設計。抽象類作為多個子類的抽象父類,可以被當成系統實現過程中的中間產品,必須有更進一步的完善。

除此之外,在使用用法上也有差別:

1、接口里只能包含抽象方法,抽象類則完全可以包含普通方法。

2、接口不能定義靜態方法,抽象類可以。

3、接口只能定義靜態常量,不能定義普通成員變量,抽象類則可以定義靜態常量,也可以定義普通成員變量。

4、接口不含構造器,抽象類可以包含構造器和構造代碼塊。

         抽象類是可以被實例化,只不過是子類對象創建的時候,創建抽象類父類對象。所以,抽象類是可以有靜態代碼塊,構造代碼塊,構造方法,抽象類就既可以有實例變量、也可以有靜態變量。         接口沒有構造器、構造代碼塊,所以,接口不能被實例化,也不可能有實例變量。

接口沒有靜態代碼塊,那么,就無法為接口定義的常量賦值,那么接口就規定:定義接口屬性是需要在聲明時直接賦值。

4、  一個類最多只能有一個直接父類,包括抽象類;但一個類可以多個實現接口,通過實現多個接口可以彌補java單繼承的不足。

當新增功能時,發現,該功能并不屬于該類的父類,就需要使用接口,來擴展一下該功能。

 

面向接口編程:

接口體現的是一種規范和實現分離的設計哲學,充分利用接口可以降低各個模塊之間的耦合性,從而提高系統的擴展性和維護性。

面向接口編程設計在這里不做太多解釋,這個不屬于現階段內容,如果有興趣可以參閱:

http://baike.baidu.com/link?url=cjLmsENJgShmA6DGWi2RBh9gccRbn7dAXgOoaEuRrBiM9voyhUof8PvFSHI-HhxEp-ueDyacewd1ZwQdDWdsxfFMOZCS4UkojZkZr5P1vDDc3kQvMJr_vbJBx3bUPWIovM1oKESe9CJAf3fvj4eAca

基于這種原則,很多軟件架構設計都倡導“面向接口”編程。而不是面向實現類編程。希望通過面向接口編程來降低程序的耦合。

工廠模式

工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,并且是通過使用一個共同的接口來指向新創建的對象。

介紹

意圖:定義一個創建對象的接口,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。

主要解決:主要解決接口選擇的問題。

何時使用:我們明確地計劃不同條件下創建不同實例時。

如何解決:讓其子類實現工廠接口,返回的也是一個抽象的產品。

關鍵代碼:創建過程在其子類執行。

應用實例: 1、您需要一輛汽車,可以直接從工廠里面提貨,而不用去管這輛汽車是怎么做出來的,以及這個汽車里面的具體實現。 2、Hibernate 換數據庫只需換方言和驅動就可以。

優點: 1、一個調用者想創建一個對象,只要知道其名稱就可以了。 2、擴展性高,如果想增加一個產品,只要擴展一個工廠類就可以。 3、屏蔽產品的具體實現,調用者只關心產品的接口。

缺點:每次增加一個產品時,都需要增加一個具體類和對象實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的復雜度,同時也增加了系統具體類的依賴。這并不是什么好事。

使用場景: 1、日志記錄器:記錄可能記錄到本地硬盤、系統事件、遠程服務器等,用戶可以選擇記錄日志到什么地方。 2、數據庫訪問,當用戶不知道最后系統采用哪一類數據庫,以及數據庫可能有變化時。 3、設計一個連接服務器的框架,需要三個協議,"POP3"、"IMAP"、"HTTP",可以把這三個作為產品類,共同實現一個接口。

注意事項:作為一種創建類模式,在任何需要生成復雜對象的地方,都可以使用工廠方法模式。有一點需要注意的地方就是復雜對象適合使用工廠模式,而簡單對象,特別是只需要通過 new 就可以完成創建的對象,無需使用工廠模式。如果使用工廠模式,就需要引入一個工廠類,會增加系統的復雜度。

http://www.runoob.com/design-pattern/factory-pattern.html

//TODO

 

class  Test{    public static void main(String[] args){        //調用工廠類獲取對象方法,傳遞對象信息        HuaTu huatu = Factory.getHuaTu("Rect");        //調用返回對象的畫圖方法        huatu.huaTu();    }} interface HuaTu{    void huaTu();}class Circle implements HuaTu{    public void huaTu(){        System.out.println("繪制圓形");    }}class Rect implements HuaTu{    public void huaTu(){        System.out.println("繪制矩形");    }}class Factory{    //接收傳入信息    static HuaTu getHuaTu(String str){        //根據傳入信息判斷返回什么類型對象        if(str.equals("Circle")){            return new Circle();        }elseif(str.equals("Rect")){                return new Rect();        }        return null;    }}


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 青州市| 盐津县| 广平县| 格尔木市| 天祝| 柳州市| 大安市| 平定县| 深泽县| 青海省| 贵州省| 永吉县| 新和县| 江津市| 吴旗县| 定日县| 理塘县| 永胜县| 明光市| 敖汉旗| 托克托县| 仁怀市| 景东| 东平县| 神木县| 岳普湖县| 华安县| 德令哈市| 泊头市| 长岭县| 津南区| 突泉县| 密云县| 长阳| 安泽县| 湟中县| 盘锦市| 江油市| 临泽县| 霍邱县| 乾安县|