NO IMAGE
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

一。抽象類

有時候,我們可能想要構造一個很抽象的父類物件,它可能僅僅代表一個分類或抽象概念,它的例項沒有任何意義,因此不希望它能被例項化。例如:有一個父類“
水果(Fruit)”,它有幾個子類“蘋果(Apple)”、“橘子(Orange)”、“香蕉(Banana)”等。水果在這裡僅僅只是作為一個分類,
顯然水果的例項沒有什麼意義(就好像一個人如果告訴你他買了一些水果但是卻不告訴你是蘋果還是橘子,你很難想象他到底買的是什麼。)。而水果類又要能被子
類化,這就要求我們使用抽象類(abstract class)來解決這個問題。

在java中,通過在class關鍵字前增加abstract修飾符,就可以將一個類定義成抽象類。抽象類不能被例項化。例如:

          定義抽象類水果(Fruit)

          public abstract class Fruit {

                  ……

          }

           如果我們試圖用以下語句來獲得一個例項,將無法編譯成功。

           Fruit fruit = new Fruit();

而我們仍然可以構造水果類的子類,如:

          子類“蘋果(Apple)”

           public class Apple extends Fruit {

                   ……

           }

          子類“橘子(Orange)”

           public class Orange extends Fruit {

                   ……

           }

這樣就達到我們的目的了。

抽象類除了能象普通類一樣可以擁有一般的屬性和方法,也可以擁有抽象方法(abstract method)。例如:

           抽象類“形狀(Shape)”擁有抽象方法draw()。

           public abstract class Shape {

                  ……

                  public abstract void draw();

                  ……

           }

抽象方法與抽象的行為相對應,通常是這個行為對父物件沒有意義,而子物件有具體動作。例如方法draw()對於類Shape沒有意義,而類
Shape的子類矩形(Rectangle)的方法draw()可以有實際的動作(根據矩形的四個頂點畫出矩形的四個邊),子類圓(Circle)的方法
draw()也可以有實際的動作(根據圓心和半徑畫出圓周)。

抽象類可以有抽象方法也可以沒有抽象方法;但是如果一個類有抽象方法,那這個類只能定義為抽象類。

           如果按照以下程式碼類“形狀(Shape)”仍然擁有抽象方法draw(),但沒有定義為抽象類,將會編譯失敗。

           public class Shape {

                  ……

                  public abstract void draw();

                  ……

           }

抽象方法還有一個特點是,它強迫子類要麼仍然保持抽象性(即不具體實現該方法並仍然定義為抽象類),要麼具體表現出這個方法的行為(實現具體的動作或者通過丟擲UnsupportedOperationException異常來表明不支援該行為)。這樣也可以強化多型性。

 

 

 

二 介面

 

下面談談介面(interface)。java語言使用關鍵字interface定義一個介面。介面也是抽象物件,它甚至比抽象類更抽象。介面中的方法都是抽象方法。

一個介面可以繼承其他介面;一個類通過關鍵字implements宣告要實現一個介面,並具體實現介面的方法。

           例如:有一個介面InterfaceA,

Java程式碼

public   interface  InterfaceA {   

         void  methodA();   

}  

 

           類ClassA實現介面InterfaceA。

Java程式碼

public   class  ClassA  implements InterfaceA {   

          public   void  methodA() {   

               System.out.println( “methodA of ClassA implements InterfaceA” );   

         }   

}  

 

如果是抽象類實現一個介面,那麼抽象類中可以不具體實現介面的方法(保持其抽象性),而由其子類去實現。

           抽象類ClassB實現介面InterfaceA,但是沒有具體實現方法methodA(),

Java程式碼

public   abstract   class  ClassBS  implements InterfaceA{           }  

 

           子類ClassBSub實現介面InterfaceA,但是沒有具體實現方法methodA(),

Java程式碼

public   class  ClassBSub implements InterfaceA{   

         public   void  methodA() {   

              System.out.println( “methodA of ClassBSub the subclass of ClassB” );   

        }   

}  

 

介面和抽象類顯著的共同點是介面和抽象類都可以有抽象方法。

介面和抽象類的不同點有:

           (1)抽象類可以有例項變數,而介面不能擁有例項變數,介面中的變數都是靜態(static)的常量(final)。

           (2)抽象類可以有非抽象方法,而介面只能有抽象方法。

 

java允許一個介面繼承多個父介面,也允許一個類實現多個介面,而這樣的多繼承有上面提到的缺點馬?

答案是沒有,這是由介面的抽象性決定的。

正如前面介紹的,在介面中不能有例項變數,只能有靜態的常量,不能有具體的方法(包含方法體),只能有抽象方法,因此也就摒棄了多繼承的缺點。

對於一個類實現多個介面的情況,因為介面只有抽象方法,具體方法只能由實現介面的類實現,在呼叫的時候始終只會呼叫實現類的方法(不存在歧義),
因此不存在多繼承的第二個缺點;而又因為介面只有靜態的常量,但是由於靜態變數是在編譯期決定呼叫關係的,即使存在一定的衝突也會在編譯時提示出錯;而引
用靜態變數一般直接使用類名或介面名,從而避免產生歧義,因此也不存在多繼承的第一個缺點。

對於一個介面繼承多個父介面的情況也一樣不存在這些缺點。

請看以下示例。

            介面A:

Java程式碼

public   interface  InterfaceA {   

         int  len =  1 ;   

         void  output();   

}  

 

            介面B:

Java程式碼

public   interface  InterfaceB {   

           int  len =  2 ;   

           void  output();   

}  

 

            介面InterfaceSub繼承介面A和介面B:

Java程式碼

public   interface  InterfaceSub  extends  InterfaceA, interfaceB {            }  

 

            類Xyz實現介面InterfaceSub:

Java程式碼

public   class  Xyz  implements  InterfaceSub {   

         public   void  output() {   

                System.out.println( “output in class Xyz.” );   

        }   

          public   void  outputLen( int  type) {   

                  switch (type) {   

                          case  InterfaceA.len:   

                                 System.out.println( “len of InterfaceA=.” type);   

                                  break ;   

                          case  InterfaceB.len:   

                                 System.out.println( “len of InterfaceB=.” type);   

                                  break ;   

                 }   

        }   

        public   static   void  main(String[] args) {   

               Xyz xyz=  new  Xyz ();   

               xyz .output();   

               xyz .outputLen();   

       }   

 

           以上程式碼不存在什麼問題,但是如果試圖編寫以下存在衝突的程式碼,則會編譯失敗。

Java程式碼

Xyz xyz =  new  Xyz();   

int  len = xyz.len;   

System.out.println(len);  

相關文章

程式語言 最新文章