主頁 > 後端開發 > Java的抽象類 & 介面

Java的抽象類 & 介面

2023-05-10 10:38:48 後端開發

抽象類

如果自下而上在類的繼承層次結構中上移,位于上層的類更具有通用性,甚至可能更加抽象,從某種角度看,祖先類更加通用,人們只將它作為派生其他類的基類,而不作為想使用的特定的實體類,例如,考慮一下對 Employee 類層次的擴展,一名雇員是一個人,一名學生也是一個人,下面將 Person 類和 Student 類添加到類的層次結構中,下圖是這三個類
之間的關系層次圖,

image-20230414175409470.png


為什么要花費精力進行這樣高層次的抽象呢?每個人都有一些諸如姓名這樣的屬性,學生與雇員都有姓名屬性,因此可以將 getName() 方法放置在位于繼承關系較高層次的通用基類中,現在,再增加一個 getDescription() 方法,它可以回傳對一個人的簡短描述,例如:

an employee with a salary of $5000000
a student majoring in computer science

在 Employee 類和 Student 類中實作 getDescription() 這個方法很容易,但是在 Person 類中應該提供什么內容呢?除了姓名之外,Person 類一無所知,當然,可以讓 Person::getDescription() 回傳一個空字串,然而,還有一個更好的方法, 就是使用 abstract 關鍵字,這樣就完全不需要實作這個方法了,

// no implementation required
public abstract String getDescription();

為了提高程式的清晰度,包含一個或多個抽象方法的類本身必須被宣告為抽象的,

public abstract class Person {
	public abstract String getDescription();
}

除了抽象方法之外,抽象類還可以包含具體資料和具體方法,例如,Person 類還保存著姓名和一個回傳姓名的具體方法,

public abstract class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public abstract String getDescription();

    public String getName() {
        return name;
    }
}

提示:許多程式員認為,在抽象類中不能包含具體方法,建議盡量將通用的域和方法(不管是否是抽象的)放在基類(不管是否是抽象類)中,

抽象方法充當著占位的角色,它們的具體實作在子類中,擴展抽象類可以有兩種選擇,

  • 一種選擇是:在子類中定義抽象類的部分方法或不定義抽象類的方法,這樣就必須將子類也標記為抽象類;
  • 另一種選擇是:在子類中定義抽象類全部的抽象方法,這樣一來,子類就不是抽象類了,例如,通過擴展 Person 抽象類,并實作 getDescription() 方法來定義 Student 類,由于在 Student 類中不再含有抽象方法,所以不必將 Student 類宣告為抽象的,

即使一個類不含抽象方法,也可以將該類宣告為抽象類,

抽象類不能被實體化,也就是說,如果一個類被宣告為 abstract,就不能創建這個類的物件,例如,運算式 new Person("Vince Vu") 是錯誤的,但可以創建一個具體子類的物件,

需要注意,可以定義一個抽象類的物件變數,但是它只能參考非抽象子類的物件,例如:Person p = new Student("Vince Vu", "Economics"); 這里的 p 是一個 Person 抽象類的物件變數,p 參考了一個 Student 非抽象子類的實體,


在 C++ 中,有一種在尾部用 =0 標記的抽象方法,被稱為純虛函式,例如:

// C++
class Person {
    public:
    	virtual string getDescription() = 0;
};

在 C++ 中,一個類只要有一個純虛函式,這個類就是抽象類,在 C++ 中,沒有提供用于表示抽象類的特殊關鍵字,

介面

介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作,

一個類可以實作(implement)—個或多個介面,并在需要介面的地方,隨時使用實作了相應介面的物件,

在下面的小節中,你會了解 Java 介面是什么以及如何使用介面,

介面概念

在 Java 程式設計語言中,介面不是類,而是對類的一組需求描述,這些類要遵從介面描述的統一格式進行定義,實作介面的類必須定義介面中宣告的所有方法,

在介面中還可以定義常量,然而,更為重要的是要知道介面不能提供哪些功能,介面絕不能含有實體域,在 Java8 之前, 也不能在介面中實作方法,(在 Java8 及之后,可以在介面中實作默認方法,)提供實體域和方法實作的任務應該由實作介面的那個類來完成,

介面中的方法都自動地被設定為 public ,介面中的域都自動地被設定為 public static final,因此,在介面中宣告方法時,不必提供關鍵字 public,

為了讓類實作一個介面,通常需要下面兩個步驟:

  1. 將類宣告為實作給定的介面,要將類宣告為實作某個介面,需要使用 implements 關鍵字
  2. 對介面中的所有方法進行定義,

介面的特性

介面不是類,尤其不能使用 new 運算子實體化一個介面:

x = new Comparable(...); // ERROR

然而, 盡管不能構造介面的物件,卻能宣告介面的變數:

Comparable x; // OK

介面變數必須參考實作了介面的類物件:

x = new Employee(...); // OK provided Employee implements Comparable

接下來,如同使用 instanceof 檢查一個物件是否屬于某個特定類一樣,也可以使用 instanceof 檢查一個物件是否實作了某個特定的介面:

if (anObject instanceof Comparable) { ... }

與可以建立類的繼承關系一樣,介面也可以被擴展,這里允許存在多條從具有較高通用性的介面到較高專用性的介面的鏈,例如,假設有一個被稱為 Moveable 的介面:

public interface Moveable {
	void move(double x, double y);
}

然后,可以以它為基礎 擴展一個叫做 Powered 的介面:

public interface Powered extends Moveable {
	double milesPerCallon();
}

雖然在介面中不能包含實體域或靜態方法,但卻可以包含常量,例如:

public interface Powered extends Moveable {
    double milesPerCallonO;
    double SPEED_LIHIT = 95; // a public static final constant
}

與介面中的方法都自動地被設定為 public —樣,介面中的域將被自動設為 public static final,

可以將介面方法標記為 public,將域標記為 public static final,有些程式員出于習慣或提高清晰度的考慮,愿意這樣做,但 Java 語言規范卻建議不要書寫這些多余的關鍵字,


可以為介面方法提供一個默認實作,必須用 default 修飾符標記這樣一個方法,

public interface Comparable<T> {
    default int compareTo(T other) {
        return 0;
    }
    // By default, all elements are the same
}

介面 & 抽象類

為什么 Java 程式設計語言還要不辭辛苦地引入介面概念?為什么不將 Comparable 直接設計成如下所示的抽象類,

// why not?
abstract class Comparable {
	public abstract int compareTo(Object other);
}

然后,Employee 類再直接擴展這個抽象類,并提供 compareTo() 方法的實作:

// why not?
class Employee extends Comparable {
	public int compareTo(Object other) { ... }
}

非常遺憾,使用抽象類表示通用屬性存在這樣一個問題:每個類只能擴展于一個類,假設 Employee 類已經擴展于一個類,例如 Person,它就不能再像下面這樣擴展第二個類了:

class Employee extends Person, Comparable // Error

但每個類可以像下面這樣實作多個介面:

class Employee extends Person implements Comparable // OK

有些程式設計語言允許一個類有多個父類,例如 C++,我們將此特性稱為多重繼承(multiple inheritance),而 Java 的設計者選擇了不支持多繼承,其主要原因是多繼承會讓語言本身變得非常復雜(如同 C++),效率也會降低(如同 Eiffel),

實際上,介面可以提供多重繼承的大多數好處,同時還能避免多重繼承的復雜性和低效性,

可以將介面看成是沒有實體域的抽象類,但是這兩個概念還是有一定區別的,介面 & 抽象類的區別:

  • 它們可以包含的內容不同:
    • 抽象類中可以包含資料域(實體域、static 域、final 域)、具體方法、抽象方法,
    • 介面中不能包含實體域,但可以包含常量(static final 域)、默認方法,介面中的方法都自動地被設定為 public ,介面中的域都自動地被設定為 public static final
  • 它們的用途不同:
    • 抽象類的用途是:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知),這時需要使父類是抽象類,在子類中提供方法的實作(抽象類和普通的類是十分相似的:普通類中有的,抽象類中也都可以有,只是抽象類中可以有抽象方法)
    • 介面的用途是:介面主要用來描述類具有什么功能,而并不給出每個功能的具體實作,實作介面的類必須定義介面中宣告的所有方法,確保一個類(實作介面的類)實作一個或一組特定的方法,
  • 在 Java 程式設計語言中,每個類只能夠擁有一個父類,但卻可以實作多個介面

參考資料

《Java核心技術卷一:基礎知識》(第10版)第 5 章:繼承 5.1.9 抽象類

《Java核心技術卷一:基礎知識》(第10版)第 6 章:介面、lambda 運算式與內部類 6.1 介面

本文來自博客園,作者:真正的飛魚,轉載請注明原文鏈接:https://www.cnblogs.com/feiyu2/p/17387040.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552084.html

標籤:其他

上一篇:【11個適合畢設的Python可視化大屏】用pyecharts開發拖拽式可視化資料大屏

下一篇:返回列表

標籤雲
其他(158758) Python(38125) JavaScript(25412) Java(18025) C(15225) 區塊鏈(8263) C#(7972) AI(7469) 爪哇(7425) MySQL(7175) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5338) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4570) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1972) 功能(1967) Web開發(1951) HtmlCss(1934) python-3.x(1918) 弹簧靴(1913) C++(1913) xml(1889) PostgreSQL(1875) .NETCore(1860) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Java的抽象類 & 介面

    抽象類:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知)。這時需要使父類是抽象類,在子類中提供方法的實作。

    介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作。 ......

    uj5u.com 2023-05-10 10:38:48 more
  • 【11個適合畢設的Python可視化大屏】用pyecharts開發拖拽式可視

    你好,我是@馬哥python說,一枚10年程式猿。 一、效果演示 以下是我近期用Python開發的原創可視化資料分析大屏,非常適合畢設用,下面逐一展示:(以下是截圖,實際上有動態互動效果哦) 以下大屏均為@馬哥python說的個人原創,請勿轉載。 1.1 影視劇分析大屏 1.2 豆瓣電影分析大屏A ......

    uj5u.com 2023-05-10 10:27:16 more
  • 【11個適合畢設的Python可視化大屏】用pyecharts開發拖拽式可視

    你好,我是@馬哥python說,一枚10年程式猿。 一、效果演示 以下是我近期用Python開發的原創可視化資料分析大屏,非常適合畢設用,下面逐一展示:(以下是截圖,實際上有動態互動效果哦) 以下大屏均為@馬哥python說的個人原創,請勿轉載。 1.1 影視劇分析大屏 1.2 豆瓣電影分析大屏A ......

    uj5u.com 2023-05-10 10:25:24 more
  • Java的抽象類 & 介面

    抽象類:在子類繼承父類時,父類的一些方法實作是不明確的(父類對子類的實作一無所知)。這時需要使父類是抽象類,在子類中提供方法的實作。

    介面(interface)技術主要用來描述類具有什么功能,而并不給出每個功能的具體實作。 ......

    uj5u.com 2023-05-10 10:24:35 more
  • C語言快速入門教程1快速入門 2指令 3條件選擇

    快速入門 什么是C語言? C是一種編程語言,1972年由Dennis Ritchie在美國AT & T的貝爾實驗室開發。C語言變得很流行,因為它很簡單,很容易使用。今天經常聽到的一個觀點是--"C語言已經被C++、Python和Java等語言所取代,所以今天何必再去學習C語言"。我很不贊同這種觀點。 ......

    uj5u.com 2023-05-10 10:23:23 more
  • 高效c語言1快速入門

    本章將開發你的第一個C語言程式:傳統的 "Hello, world!"程式。然后討論一些編輯器和編譯器的選項,并闡述移植性問題。 Hello, world! #include <stdio.h> #include <stdlib.h> int main(void) { puts("Hello, wo ......

    uj5u.com 2023-05-10 10:22:59 more
  • 怎樣成為優秀的后端工程師

    本文翻譯自國外論壇 medium,原文地址:https://medium.com/@pradeesh-kumar/how-to-become-a-good-backend-engineer-9da75202a104 讓我們一起看看國外開發者認為優秀后端工程師需要掌握哪些技能。 誰是后端工程師? 本質 ......

    uj5u.com 2023-05-10 07:38:38 more
  • Django筆記三十九之settings配置介紹

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記三十九之settings配置介紹 這一篇筆記介紹 Django 里 settings.py 里一些常用的配置項,這些配置有一些是在之前的筆記中有過介紹的,比如 logging 的日志配置,session 的會話配置等,這里就只做一下簡單的 ......

    uj5u.com 2023-05-10 07:37:28 more
  • 【redis】哨兵監控原理

    redis-主從模式弊端: 一、master節點例外shutdown后,從機原地待命,從機資料可以查詢(不可以寫入),等待主機重啟歸來 二、復制延時,信號衰減 redis-哨兵監控: 是什么? 哨兵即為吹哨人,可以巡查監控后臺master主機是否故障,如果故障可以根據投票數自動將一個從庫轉換為新的m ......

    uj5u.com 2023-05-10 07:32:04 more
  • 實驗五 Java多執行緒程式設計

    實驗五 Java多執行緒程式設計

    實驗目的
    1. 掌握Runnable介面實作多執行緒的方法
    2. 掌握Thread類實作多執行緒的用法
    3. 掌握Java語言中多執行緒編程的基本方法 ......

    uj5u.com 2023-05-10 07:26:53 more