簡體   English   中英

抽象類,接口或抽象方法的用途是什么

[英]What is the use of an abstract class, interface or an abstract method

我對於為什么使用抽象類或接口來實現或擴展感到困惑。 接口不包含任何代碼,抽象方法也不包含任何代碼。 那為什么我們要使用它們。 為什么我們不直接創建方法並在類中定義它們,而是使用接口或抽象類。 它們不包含任何代碼,我們需要在我們的類中對其進行擴展后再對其進行定義。 為什么我們不在自己的類中定義這些方法,而是擴展接口然后定義它們。 我發現此類問題在stackoverflow中已問過幾次,但無法理解答案。 誰能用簡單的方式解釋一下

抽象和接口的力量來自於您可以分離職責並編寫模塊化代碼的事實:您(或其他人)代碼的一部分可能只關心您擁有Animal並提供了處理動物的設施,而無需知道他們如何移動或進食。 代碼的不同部分可能只關心定義具體的動物,例如DogBird等等,並詳細說明了它們如何實際實現其所有功能。

通過使具體類(狗,鳥等)擴展一個通用的抽象接口(動物),您可以在為抽象接口編寫的庫中使用現在和將來的任何具體類-無需要求圖書館作者更改圖書館以容納新的動物,圖書館作者不需要知道如何具體實現功能。

例如,如果您有兩個單一算法FeedBreakfastFeedDinner ,則需要成員函數Animal::gobble() ,那么在沒有繼承的情況下,您需要為每種動物實現每種算法-即,最終得到M * N量代碼! 通過使用一個通用的抽象接口,您可以將其簡化為M + N M算法和N具體類,並且雙方都不需要知道對方-他們都需要知道接口。

抽象類背后的想法是,您可以定義一組相似類的某些通用功能,但將其他細節留給實現(擴展)類。 在某種程度上,它們類似於接口,不同之處在於您可以實際實現抽象類中的某些功能。

但是,有什么意義,我聽到你問了嗎? 嗯,盡管您也可以在一個具體的(非抽象的)基類中完成一次通用代碼,但是您只需編寫一次即可。 但是您也可能不希望其他程序員實例化基類,因此這才是抽象類真正強大的地方。

讓我舉一個例子來說明我的觀點。 想象一下,您正在編寫一個程序,對動物園中的所有動物進行分類。 動物可以分為某些類型,如鳥類,爬行動物,哺乳動物,昆蟲,蜘蛛,魚類等,然后分為其種類,如狗,貓,鸚鵡或袋鼠。 基類Animal可以為所有這些提供某些通用功能。 它可能具有一個稱為eat()的函數,所有動物都以類似的方式執行該函數,因此該函數被寫出以描述動物進食的過程。 它可能包含另一個函數walk(),但這是抽象的,因為不同的動物將以不同的方式實現它。 Animal類的所有子類都需要實現此方法。

這樣做的主要好處是,您可以在代碼中的某處調用以動物為參數的函數。 您知道可以在此參數上調用eat()和walk()函數,因為所有動物都可以進食和行走。 這被稱為多態,是面向對象編程的重要特征。

希望對您有所幫助。 如果您仍然看不到抽象類的價值,請隨時討論或提出其他問題。

靜態類型語言需要使用此方法來啟用多態。 也就是說,您可以根據抽象基類編寫代碼。 然后,您可以“插入”任何子類作為擴展。 這稱為Liskov替換原理 ,或打開/關閉原理 從技術上講,這稱為動態綁定 即,將在運行時根據子類選擇要調用的方法。

對於動態類型的語言,情況則完全不同。 我不知道PHP是否是動態類型的(我懷疑是這樣),但是例如在Ruby或Javascript中,您可以根據符合特定接口的任何對象進行編程。 就是說,如果您的代碼期望一個對象具有一個稱為Print的方法,則可以用其他任何一個也具有Print方法的對象代替,而無需派生一個通用的基類。 將在運行時查找該方法,這就是為什么將這些語言稱為“ 動態 ”的原因。

希望這可以幫助!

要建立協議時,可以使用抽象類或接口。

聽起來很簡單,但這是一個非常強大的概念。 如果您被迫遵守規則,那么您將無法違反規則。 如果您不能違反規則,請遵守該協議。 因此,實現您的接口的所有類在本質上應該彼此兼容。 當然,人類中也有例外,他們可以通過創建代碼來打破這些規則,甚至解釋員在必須解析它們時也會哭泣,但這有點題外話:)

對於接口,假設您有一個名為“消息”的類。 這實現了名為SendMessage的接口,該接口具有Send的方法定義。

如果然后創建“消息”的兩個子類。 一個可能是“電子郵件”,另一個可能是“ InstantMessage”。

現在它們都具有方法Send(),該方法在SendMessage接口中定義,並且為空。 現在,這使您可以不同地定義Send()方法的作用。 但是,由於我們知道類Email和InstantMessage使用接口SendMessage,因此我們知道它們都具有方法Send();。

因此,您可以調用Email.Send()和InstantMessage.Send(),但要做兩件事。 接口定義了可用於多個對象的方法,但方法名稱相同。

抽象類/接口主要是設計時的考慮因素。 通過將方法定義為抽象,因此也將類定義為抽象,我們確保可以肯定地通過派生類來實現這些方法。 如果他們不執行它們,它們也會變得抽象。

接口提供了將必須實現的方法分布到不同類別中的奢侈性,因此可以實現所需數量的接口。

抽象類保證不能實例化,這是因為是泛化。 例如,在游戲中,存在一個階級玩家,但也存在一個階級后衛和前鋒。 類播放器是兩個類的父類。 並不是創建一個對象球員的做法,因為團隊需要一個特定的球員。

接口與多態有關。 每個類,根據其行為使用方法。

希望對您有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM