java面對對象入門(8)-接口vs抽象類區別

1.Java中的抽象類

用最簡單的話來講,一個抽象類就是使用keyword聲明爲abstract的abstract。它可能包含也可能不包含任何抽象方法。JVM將抽象類標識爲不完整類該類還沒有定義其完整行爲。聲明一個類abstract僅強制執行一件事:您不能建立此類的實例,僅此而已。
那麼,爲何還要費心建立一個根本沒法實例化的類呢?答案在於解決某些關鍵設計問題的方法。咱們將在本文後面介紹這一部分。
html

1.1抽象類的語法

abstract class TestAbstractClass
{
    public abstract void abstractMethod();
    public void normalMethod()
    {
        //method body
    }
}

在這裏,咱們TestAbstractClass有兩種方法,一種是抽象方法,第二種是普通方法。抽象方法。在類中使用抽象方法將迫使您將類聲明爲抽象自己。
java

1.2抽象方法

一個抽象方法,是未取代實施的方法。抽象方法給類增長了不完整性,所以編譯器但願將整個類聲明爲抽象。
在應用程序中使用抽象類的惟一方法是擴展此類。若是不abstract再次聲明其子類,則能夠實例化。子類繼承了超類的行爲,而且超類能夠保留對子類的引用的功能在不少方面增長了抽象類的重要性。
python

2.Java接口

接口是大多數Java API的另外一個基本構建塊。您將其命名爲collection,I / O或SWT,您能夠在任何地方看到它們的運行狀況。程序員

接口定義合同,實現類須要遵照這些合同。api

這些合同本質上是未實現的方法。Java已經有一個未實現方法的關鍵字,即_abstract_。Java規定任何類均可以實現任何接口,所以在接口中聲明的全部方法僅需是公共的。
oracle

2.1 接口語法

public interface TestInterface
{
    void implementMe();
}

對於上述接口,任何實現類都須要重寫implementMe()方法。
框架

2.2抽象類實現接口

當實現一個接口而且不重寫該方法即聲明實現類自己時,只有一種狀況abstract
抽象類ide

public abstract class TestMain implements TestInterface
{
    //No need to override implement Me
}

不然,您必須implementMe()在您的類中實現該方法,而沒有任何其餘例外。
非抽象類學習

public class TestMain implements TestInterface
{
    @Override
    public void implementMe() {
        // TODO Auto-generated method stub
    }
}

3.抽象類與接口

讓咱們記下抽象類和接口之間的差別以便快速查看:ui

  1. 接口具備固有的全部公共方法和_抽象_方法。您不能經過嘗試減小方法的可訪問性來覆蓋此行爲。您甚至不能聲明靜態方法。僅公開和抽象。另外一方面,抽象類能夠靈活地聲明方法。您還能夠定義受保護的可訪問性的抽象方法。此外,還能夠定義靜態方法,只要它們不是抽象的便可。容許使用非抽象靜態方法。
  2. 接口不能具備徹底定義的方法。根據定義,接口旨在提供惟一的合同。抽象類能夠具備非抽象方法,沒有任何限制。您能夠將任何關鍵字與非抽象方法一塊兒使用,就像在其餘任何類中同樣。
  3. 任何要使用抽象類的類均可以使用關鍵字擴展抽象類extends,而爲了實現接口關鍵字是implements。一個類只能擴展一個類,但能夠實現任何數量的接口。在Java中,此屬性一般稱爲多重繼承的模擬。
  4. 接口是絕對的abstract,不能實例化;Java抽象類也沒法實例化,可是若是存在main()則能夠調用它。

接下來,若是咱們既有抽象方法又有主類,可能會有一個問題,咱們能夠嘗試從中調用抽象方法main()。可是這種嘗試將失敗,由於main()方法始終是靜態的,而抽象方法永遠不會是靜態的,所以您永遠沒法訪問靜態方法內部的任何非靜態方法。

4.什麼時候使用抽象類以及什麼時候使用接口

始終記住,在接口或抽象類之間進行選擇既不是/也不是方案,在這種狀況下,選擇未經適當分析的任何人都會產生相同的結果。瞭解當前問題後,必須很是明智地作出選擇。讓咱們嘗試在這裏添加一些智慧。

4.1抽象類的部分行爲

抽象類使您能夠定義一些行爲。它使它們成爲應用程序框架內的優秀候選人。
讓咱們以HttpServlet爲例。若是要使用Servlets技術開發Web應用程序,則必須繼承該類。衆所周知,每一個servlet都有明確的生命週期階段,即初始化,服務和破壞。若是咱們建立了每一個servlet,咱們必須一次又一次地編寫關於初始化和銷燬的同一段代碼。固然,這將是一個很大的痛苦。
JDK設計人員經過製做HttpServlet抽象類來解決此問題。它具備爲初始化Servlet和銷燬Servlet而編寫的全部基本代碼。您只須要重寫某些方法便可在其中編寫與應用程序處理相關的代碼。有道理吧!
可使用界面添加上述功能嗎?不,即便能夠,對於大多數無辜的程序員來講,設計也將是一個地獄。

4.2僅合約接口

如今,讓咱們看一下接口的用法。接口僅提供合同,實現類的責任是實現提供給它的每一個合同
若是隻想定義class的特徵,而且要強制全部實現實體實現這些特徵,那麼接口是最合適的。

4.3demo

我想以Map集合框架中的接口爲例。它僅提供規則,以及map在實踐中應如何表現。例如,它應存儲鍵值對,應使用鍵等訪問該值。這些規則在接口中採用抽象方法的形式。
全部實現類(例如HashMap,HashTable,TreeMap或WeakHashMap)均以不一樣方式實現全部方法,所以與其餘方法相比具備不一樣的功能。
一樣,接口可用於定義職責分離。例如,HashMap實現3個接口:MapSerializableCloneable。每一個接口定義了各自的職責,所以實現類選擇要實現的對象,所以將提供有限的功能。

5.接口中的Java 8默認方法

使用Java 8,您如今能夠在接口中定義方法。這些稱爲默認方法。默認方法使您能夠向庫的接口添加新功能,並確保與爲這些接口的較早版本編寫的代碼二進制兼容。
顧名思義,Java 8中的默認方法就是默認的。若是不重寫它們,則它們是調用方類將調用的方法。
默認方法

public interface Moveable {
    default void move(){
        System.out.println("I am moving");
    }
}

在上面的示例中,Moveable接口定義了一種方法,move()而且還提供了默認實現。若是有任何類實現此接口,則無需實現它本身的move()方法版本。它能夠直接調用instance.move()

public class Animal implements Moveable{
    public static void main(String[] args){
        Animal tiger = new Animal();
        tiger.move();       //I am moving
    }
}

而且,若是類願意定製行爲,那麼它能夠提供本身的定製實現並重寫該方法。如今將調用它本身的自定義方法。

public class Animal implements Moveable{
      
    public void move(){
        System.out.println("I am running");
    }
      
    public static void main(String[] args){
        Animal tiger = new Animal();
        tiger.move();       //I am running
    }

5.1Java 8中抽象類和接口之間的區別

若是您看到了,咱們如今也能夠提供帶有接口的部分實現,就像抽象類同樣。所以,從本質上說,接口與抽象類之間的界限變得很是狹窄。它們如今提供幾乎相同的功能。
如今,只有一個很大的不一樣,即您不能擴展多個類,而能夠實現多個接口。除了這種差別以外,您還能夠經過接口實現任何可能的功能,這些接口可使抽象類成爲可能,反之亦然。
但願您在Java中找到有關接口和抽象類的足夠信息。
學習愉快!
更多精彩請關注公衆號【lovepythoncn】

相關文章
相關標籤/搜索