Java 抽象類與介面

来源:http://www.cnblogs.com/qifengshi/archive/2016/07/18/5682255.html
-Advertisement-
Play Games

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


Java 抽象類

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

抽象類的特點

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

[public] abstract 返回類型 方法名(參數列表);

抽象方法是沒有方法體的 ,所以方法名寫完就會加;表示方法聲明結束,抽象法方法體用abstract修飾,表示這是一個抽象的方法,訪問修飾符只能用public或者是protected,或者是預設訪問許可權,就是不能用private,因為根本無法去繼承
同樣,抽象類的格式如下:

[public] abstract class 類名{
    [public] abstract 返回類型 方法名(參數列表);
}

抽象類的是前面加abstract修飾,表示這個是一個抽象類,訪問修飾符只能用public或者是protected,或者是預設訪問許可權,不能用private的原因和上面一樣。
抽象類創造的意義是將方法的聲明與方法的實現分隔開,從而實現多態。那麼他就具有如下的特點:

  1. 抽象類不能被實例化,也就是說不能直接創建一個抽象類的對象,但抽象類是可以有構造函數的,如果是有參構造函數,則子類要去顯示調用它。
  2. 抽象類是用來被繼承的,方法是要被覆寫的,如果子類繼承了抽象的父類,則需要覆寫父類的抽象方法,如果沒有覆寫,則子類必須也要定義為抽象類。
  3. 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{
}

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

  1. 一個類是可以實現多個介面的,這在一定程度上實現了Java的多繼承。
  2. 介面是不能被實例化,不同於抽象類,介面的內部只能由成員變數和抽象方法,是不可以存在靜態變數塊,以及構造器的。
  3. 我們是可以聲明一個介面類型的變數,但是只能引用一個實現了這個介面的類。
  4. 同抽象方法,實現了介面的類必須實現介面的所有方法,否則就會變成抽象類。

介面舉例

看過抽象的例子,我們可能想,我們把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);
    }
}

介面總結

介面和抽象雖然都是通過抽象的方法來提供我們實現多態的方式,但是他們卻是兩個不同的設計思想。這裡關於介面的講解比較簡單,關於介面自身的繼承,介面內部包含其他介面,以及利用介面來實現回調等等留在以後的文章專門來說。這裡主要是通過對比來瞭解抽象和介面。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 面向對象是一種開發思想,最應該記住的一句話是萬物皆對象。為了讓程式更好的被理解和編寫,把現實生活中描述事物的方式和思路融合進入,就成了面向對象的思想。把生活中的事物融合進程式中那麼就需要描述,描述分為特征和行為兩方面,而不同類別的對象特征和行為具有巨大的差異,為了更好的制定描述每一類事物的方式,那麼 ...
  • 在網上看到別人的代碼,寫下來留著看,歡迎各位指教,有沒有工廠模式的學習資料啊,留下給小弟學習學習. 首先寫個Model類,實現業務實體,我的比較簡單,只有三個欄位 View Code 1 public class LoginModel 2 { 3 #region 4 5 private int _A ...
  • 背水一戰 Windows 10 之 MVVM(Model-View-ViewModel): 通過 Binding 或 x:Bind 結合 Command 實現,通過非 ButtonBase 觸發命令 ...
  • .NET Core / ASP.NET Core 1 RTM發佈兩周後,社區也很積極,收到了非常多的反饋,上周五微軟的scott Hunter 在dotnet團隊官方博客上發佈了.NET Core全新的路線圖 https://blogs.msdn.microsoft.com/dotnet/2016/ ...
  • /// <summary> /// 把dataset數據轉換成json的格式 /// </summary> /// <param name="ds">dataset數據集</param> /// <returns>json格式的字元串</returns> public static string G ...
  • 一、概述 1.為什麼要用JDBC 資料庫是程式不可或缺的一部分,每一個網站和伺服器的建設都需要資料庫。對於大多數應用程式員(此處不包含資料庫開發人員)來說,我們更多的不是在DBMS中對資料庫進行操縱,而是在我們編寫的程式中對資料庫進行訪問,Java程式中一般都是通過JDBC來連接伺服器併進行增刪改查 ...
  • 思路是先用curl抓取網頁源碼,然後以關鍵字尋找出圖片網址。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> void get_key_from_str(char *origin, c ...
  • 一、在 Spring Config 文件中配置 Bean 時,有時候需要在 Bean 的配置里添加 系統部署的細節信息, 如文件路徑,數據源配置信息。而這些部署細節實際上需要在配置文件外部來定義。 二、Spring 提供了一個 PropertyPlaceholderConfigurer 的 Bean ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...