首頁  >  文章  >  Java  >  Java 抽象類別與介面

Java 抽象類別與介面

伊谢尔伦
伊谢尔伦原創
2016-12-05 13:34:211004瀏覽

Java 抽象類別

我們父類別設定了一些方法,設定的主要目的是讓子類別繼承父類別去覆寫那些方法,來展示不同的結果。換句話說,我們不關心父類別方法裡的具體實現,反正會被子類別的方法覆寫,那麼我們就可以讓父類別更抽像一下,抽像到只有方法的聲明,而沒有方法體。我們管這種方法叫做抽象方法,管包含抽象方法的類別叫做抽象類別。

抽象類別的特徵

抽象類別裡只要含有一個或一個以上的抽象方法就是抽象類,但如果一個抽象方法都沒有,那麼這個抽象類別也沒有建立的意義。抽象方法是具有以下格式的方法

[public] abstract 返回類型方法名(參數列表); 
抽象方法是沒有方法體的,所以方法名寫完就會加;表示方法聲明結束,抽像法方法體用abstract修飾,表示這是一個抽象的方法,存取修飾符只能用public或protected,或是預設存取權限,就是不能用private,因為根本無法去繼承 
同樣,抽象類別的格式如下:

[public] abstract class 类名{
    [public] abstract 返回类型 方法名(参数列表);
}

抽象類別的是前面加abstract修飾,表示這個是抽象類,存取修飾符只能用public或是protected,或是預設存取權限,不能用private的原因跟上面一樣。 
抽象類別創造的意義是將方法的宣告與方法的實作分隔開,從而實現多態。那麼他就具有如下的特點:

抽象類別不能被實例化,也就是說不能直接創建一個抽象類別的對象,但抽象類別是可以有建構函數的,如果是有參構造函數,則子類別要去顯示調用它。
抽象類別是用來被繼承的,方法是要被覆寫的,如果子類別繼承了抽象的父類,則需要覆寫父類別的抽象方法,如果沒有覆寫,則子類別必須也要定義為抽象類別。 
abstract是不能與private static,final 修飾符一起使用來修飾方法。

這裡我們解釋一下第三點,abstract不能與private一起用,因為private修飾的方法和類,都是無法再類之外被訪問到。也就沒有繼承的可能性。 abstract不能和static一起用,是因為abstract的作用是實現多態性,而實現多態則依賴繼承和覆寫。 static修飾的方法雖能被子類別所繼承,但是我們修改了繼承後的方法時,這個就不能算作是覆寫,而是父類的方法被隱藏掉了,只有通過父類名.方法名的形式顯示呼叫它,這個實作不了多態。從另一個角度來看,靜態的方法是編譯的時候就確定了,無法實現後期綁定,也就不存在運行時在決定方法呼叫的可能。所以static修飾的方法是可以繼承,但無法實現多態,自然就不能跟abstract一起使用。 
abstract不能和final一起使用的原因和上面一樣,final修飾的方法無法被繼承,自然也談不上多態,所以abstract無法和final一起用。

抽象類別舉例

我們把上文多態的例子,繼續修改,抽象化。我們把Animal的程式碼改成如下樣子。

public abstract class Animal {    
  abstract void run();
}

我們Dog,Cat類別的程式碼不需要改變。

public class Dog extends Animal{
    @Override
    public void run() {
        System.out.println("狗在奔跑");
    }
}public class Cat extends Animal{
    @Override
    public void run() {
        System.out.println("猫在奔跑");
    }
}

其他Print類,和Test類的程式碼也保持不變,程式碼如下:

public class Print {    
    public void print(Animal animal) {
        animal.run();
    }
}
public class Test {    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();        
        new Print().print(dog);        
        new Print().print(cat);
    }
}

我們可以看出抽象類和之前普通類,在其他地方的改動基本上是沒有的,只是將方法變得抽象,意義上更加明確。

抽象總結

創建抽象類別和抽象方法是很有意義的,他能讓我們設計類別的時候使類別的含義更加明確,透過抽象的思想,讓類別變得更加通用,聲明一系列的方法來告訴使用者打算怎麼去使用它。

Java 介面

介面可以看出一種協議,一種要求,我們繼承他來知道我們可以做什麼,具體怎麼做則取決與我們。例如KFC就是一個接口,我們一看他就知道裡面有買漢堡,炸雞,可樂,但是具體的味道和服務又會根據不同的店,有不同的樣子,這就是接口的意義。所以我們這裡也可以看出介面裡的方法也應該是抽象的。

介面的特點

Java中介面的寫法如下:

[public] interface InterfaceName {
         成员变量
         方法声明
}

介面區別於類,他不是用class來修飾,他用特定的interface關鍵字,存取修飾符與class一致,可以用public或缺省。裡面只有抽象方法和成員變數兩種內容。成員變數會預設加入public static final意為成員變數歸類所有,存取權限是最大的,但是不能別繼承和修改。這也看出介面是因為不能被實例化,才會這樣約定的,介面的成員變數不允許為空,在定義的時候就要賦值給他。 而介面的方法則預設為抽象方法,預設加入public abstract和抽象方法一樣,只能寫方法宣告。 
不同於我們用extends去繼承一個類別,我們用implements 來表示實作這個介面。

class ClassName implements Interface1{
}

介面作為一個特殊的存在,是有一些他的獨特的地方的。

一个类是可以实现多个接口的,这在一定程度上实现了Java的多继承。 
接口是不能被实例化,不同于抽象类,接口的内部只能由成员变量和抽象方法,是不可以存在静态变量块,以及构造器的。 
我们是可以声明一个接口类型的变量,但是只能引用一个实现了这个接口的类。 
同抽象方法,实现了接口的类必须实现接口的所有方法,否则就会变成抽象类。 
接口举例

看过抽象的例子,我们可能想,我们把Animal从抽象换成接口,不就实现了一个接口的例子嘛,其他地方基本也不用去改动。但这显然是错的。我们并不能去说Animal是一个接口,我们上面说了,接口是一种协议,规定我们能做什么,而不是一个事物的抽象。从这里我们也能看出接口和抽象的不同,抽象更多的是一种重构而产生的东西,我们先有dog,cat类,然后才会把他们共性的东西提取出来,放到一个更通用,更抽象的父类Animal中,而我们发现Animal不需要管run方法是怎么实现的,所以我们将run方法设定为抽象的方法,从而将Animal类设为抽象类,等待去=继承者来实现run。这是一种从下而上的设计思想。但是接口不是,接口一开始就是设定好的,我们根据设定好的接口从上往下去写。接口先规定好了有什么方法,然后我们再去具体实现他。这是一种从上而下的设计思想。 
所以,我们不能将Animal设为接口,但是我们可以将Print设为接口,他规定我们有一个print()方法,代码如下:

public interface Print {    
  void print(Object obj);
}

那我们就可以写一个新的类去实现这个Print接口。代码如下:

public class SimplePrint implements Print{
    @Override
    public void print(Object obj) {
        ((Animal)obj).run();
    }
}

除了Test类以外,其他地方都不需要改变。我们Test类代码如下:

public class Test {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();        
        Print print = new SimplePrint();        
        print.print(dog);        
        print.print(cat);
    }
}

接口总结

接口和抽象虽然都是通过抽象的方法来提供我们实现多态的方式,但是他们却是两个不同的设计思想。这里关于接口的讲解比较简单,关于接口自身的继承,接口内部包含其他接口,以及利用接口来实现回调等等留在以后的文章专门来说。这里主要是通过对比来了解抽象和接口。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn