抽象類和接口的定義以及區別


抽象類

定義

在面向對象的概念中,所有的對象都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。

解釋

比如一個food類,我們知道他是一個食物,但是不知道它的形狀、大小、味道等等,所以它是抽象的,需要一個具體的餅干,面條來給它特定的描述。

特點

  • 1) 不能被實例化

這個我考慮很久,查閱了一些資料,個人理解有幾點:

  1. 空間分配,內存垃圾問題。在實例化對象的時候(new food())會開辟一個堆內存空間,而它沒有實現的方法,是個東西,但沒用。那就是垃圾。
  2. 安全。如果調用未實現的類就會報異常。比如
public abstract class Food{
              
            public void print(){
                System.out.println("un_abstract method");
            }
             
            public abstract void abstractmethod();
      }

假設我們new一個對象出來,Food food = new Food(),那么執行food.abstractmethod呢?
3. 面向對象思想不允許。可能也是最重要的吧。面向對象領域的一切都是對象,抽象在問題領域是沒有概念的。在映射到現實社會的模擬,抽象是沒有意義的。簡單的來說,你實例化一個抽象的東西能干嗎,沒有實際的意義,違背了面向對象思想。

關於這三點,屬於個人觀點,希望得到探討和批評,不保證正確性

  • 2) 抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類一樣。
public abstract class Person{
    private String name;  // 變量
    private String address;
    public Employee(String name, String address){  // 構造方法
        this.name = name;
        this.address = address;
    }
    
    public abstract void cry();  //  抽象方法
    
    public void jump(){  // 普通方法
        System.out.println(this.name + "跳起來了")
    }
    
    // getter/setter 略
}
  • 3)類中有抽象方法就必須定義為抽象類,抽象類中不一定包含抽象方法;

關於抽象類中不一定包含抽象方法,這個也有點鑽牛角尖問題。如果一個抽象類不包含任何抽象方法,為何還要設計為抽象類?所以暫且記住這個概念吧,不必去深究為什么。

  • 4)抽象類必須被繼承使用。子類必須重寫父類所有抽象方法或者聲明自己為抽象類(實現部分抽象方法);
public class Employee extends Person{
    private int number;
    
    public Employee(String name, String address, int number){
        super(name,address);
        this.number = number;
    }
    
    @Override
    public void cry(){  // 
        System.out.println(this.number + "在叫")
    }
    
    // public abstract void *();
    // 子類也可以繼續聲明自己的抽象方法,繼續被繼承實現
}
  • 5)abstract不能與final並列修飾同一個類。
  • 6)abstract 不能與private、static、final或native並列修飾同一個方法。
  • 7)一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。

為什么需要抽象類?

抽象方法和抽象類看上去是多余的,對於抽象方法,不知道如何實現,定義一個空方法體不就行了嗎,而抽象類不讓創建對象,看上去只是增加了一個不必要的限制。

引入抽象方法和抽象類,是Java提供的一種語法工具,對於一些類和方法,引導使用者正確使用它們,減少被誤用。

使用抽象方法,而非空方法體,子類就知道他必須要實現該方法,而不可能忽略。

使用抽象類,類的使用者創建對象的時候,就知道他必須要使用某個具體子類,而不可能誤用不完整的父類。

無論是寫程序,還是平時做任何別的事情的時候,每個人都可能會犯錯,減少錯誤不能只依賴人的優秀素質,還需要一些機制,使得一個普通人都容易把事情做對,而難以把事情做錯。抽象類就是Java提供的這樣一種機制。

接口

在軟件工程中,接口泛指供別人調用的方法或者函數。從這里,我們可以體會到 Java 語言設計者的初衷,它是對行為的抽象。在 Java 中,定一個接口的形式如下:

[public] interface InterfaceName {
 
}

特征

  • 1)接口中可以含有變量和方法

但是要注意,接口中變量只能是 public static final變量,用其他報錯。

方法且只能是 public abstract 方法,用其他關鍵字,比如 private、protected、static、 final 等修飾會報編譯錯誤

  • 2)接口中的方法必須都是抽象方法
  • 3)允許一個類遵循多個特定的接口
class ClassName implements Interface1,Interface2,[....]{
}

如果一個非抽象類遵循了某個接口,就必須實現該接口中的所有方法。對於遵循某個接口的抽象類,可以不實現該接口中的抽象方法。

抽象類和接口的區別

1. 語法層面上

  • 抽象類可以提供成員方法的實現細節,而接口中只能存在public abstract 方法;

  • 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的;

  • 接口中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;

  • 一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。

說明抽象類只是類的另一種形式。而接口是一個公共的方法集合,不能有別的,一旦用了一個方法還得全部都得用,很純粹,很牛XX

2. 設計層面上

要真正理解和區分,就要在設計層面上下功夫了,這樣才能知道在什么場景下用它。

  • 抽象類是對一種事物的抽象,即對類抽象,而接口是對行為的抽象。

舉個栗子,飛機和鳥是不同的事物,但有一個共同的特征就是會飛。因此我們可以設計的時候,設計AirplanBird兩個類,但是一個動作,一種行為,不是一類事物的抽象描述。所以就可以設計一個接口Fly,包含方法fly(),然后Airplane和Bird分別根據自己的需要實現Fly這個接口。

然后至於有不同種類的飛機,比如戰斗機、民用飛機等直接繼承Airplane即可,對於鳥也是類似的,不同種類的鳥直接繼承Bird類即可。

從這里可以看出,類繼承屬於‘是不是’的問題,你屬不屬於飛機類,鳥類。接口實現是‘有沒有’的問題,你有沒有飛這個功能。

  • 抽象是對類的抽象,是一種模板設計,而接口是對行為的抽象,是一種行為的規范。

我認為這就話就是精髓所在。直接再舉起來一個栗子:門和報警

門都有open()close()兩個動作,但現在要給門加上alarm(),這就要分析一下了。

Dooropen()close()alarm() 屬於兩個不同范疇內的行為,open() 和 close() 屬於門本身固有的行為特性,而 alarm() 屬於延伸的附加行為。門也分很多種,玻璃門、防盜門、推拉門等等。不是所有的都具有報警功能。以后添加報警裝置,也只是增加了一個報警功能。

因此最好的解決辦法是單獨將報警設計為一個接口,包含 alarm() 行為,Door 設計為單獨的一個抽象類,包含 openclose 兩種行為。再設計一個報警門繼承 Door 類和實現 Alarm 接口。

即:

public abstract class Door{
   public abstract void open();
   public abstract void close();
}

interface Alarm{
    void alarm();
}


class AlarmDoor extends Door implements Alarm{
     @Override
    void oepn() {
      //....
    }
     @Override
    void close() {
      //....
    }
     @Override
    void alarm() {
      //....
    }
}

參考資料:

https://www.runoob.com/w3cnote/java-abstract-interface-different.html

https://www.runoob.com/java/java-abstraction.html

https://blog.csdn.net/chenssy/article/details/12858267


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM