[英]What is the purpose of abstract classes?
我試圖在PHP中學習OOP,我對接口和抽象類有一些困惑。 它們都不包含任何實現,只包含定義,並且應該通過它們的子類來實現。 抽象類的哪一部分明確區別於接口? 另外,由於它們有明顯的相似性,我應該根據什么原因決定使用一個而不是另一個?
可以創建包含具體成員的抽象類,例如方法或屬性。 您仍然無法直接實例化抽象類,但任何實例化的子類都可以從抽象類中定義的已實現成員中受益。
相比之下,接口從不包含任何實現邏輯。 它由每個實現類提供,以提供接口中定義的所有成員的實現。
在我如何查看其區別方面,一個子類的抽象的是,一類型的。 例如, Dog
是Animal
。 我將界面視為一種關系。 例如, ICanDisplayImages
告訴我實現類可以顯示圖像,但不會告訴我類實際代表什么。
abstract
類在自身和子類之間形成一個is-a關系,而一個interface
創建一個follow-a關系。 因此,抽象類比接口更具體,它們也可能包含具體實現(例如模板方法 ),而接口定義實現類必須遵循的契約方法集。 這是一個更高級別的抽象,因為實現類不一定是抽象類。 用它來標准化你的API。
相關問題: https : //stackoverflow.com/search?q = abstract + vssinterface
它們都不包含任何實現..
抽象類可以實現全部或部分方法。 但主要的理念是擴展現有的抽象類,在子類中添加新方法(擴展基本功能)。
在子類中,您只能擴展一個類(抽象類)。 抽象類定義必須實現的功能,或者只是通過子類中的其他方法擴展。
接口用於定義類行為。 你可以實現多個接口(並說我的子類必須這樣做,這個和這個thigs!),但是你只能擴展一個抽象類。
除了在其他答案中描述的OOP哲學之外,我認為抽象類的主要用途是一種骨架。
當您設計應用程序或與團隊合作時,它非常有用,因為您有一個基本代碼可以使用並擴展它接近界面但具有更高級的工作流程。
抽象類和接口之間的主要區別在於接口定義了常見行為,其中抽象類是繼承的基礎類。 換句話說,抽象類定義了子類可能共享的一些核心方法和屬性集。 考慮一個定義許可證的類。 所有許可證都具有某種類型的ID號,並頒發給某個人或組。 許可證類可以通過驅動程序許可證類,自行車許可證類和狩獵許可證類擴展,等等。 將許可類抽象化的主要原因是它定義了許可的抽象概念。 沒有許可證這樣的東西,所以通過聲明類抽象,它不能被實例化。
另一方面,接口根本不定義對象。 它定義了方法簽名。 任何實現接口的非抽象類都必須為接口中的所有方法提供實現。 這里的優點是該方法提供跨不同類型對象的公共接口,例如compareTo()在與Strings或任何其他對象一起使用時看起來相同。
如果方法未定義為抽象,則抽象類可以包含方法實現。 如果該方法被定義為抽象,則它不包含實現,但它需要由其繼承者實現。 抽象類不能實例化,而只是繼承自,以便繼承者允許它使用其行為。
接口只定義方法簽名,從中繼承的任何類都必須實現接口中包含的所有方法。
通常,接口用於定義合同,因此您可以進行類型檢查。 還有一種稱為“對接口編程”的編程風格,這是一個好主意。 請參閱依賴性倒置原則 :
A.高級模塊不應該依賴於低級模塊。 兩者都應該取決於抽象。
B.抽象不應該依賴於細節。 細節應該取決於抽象。“
因此,如果您定義函數和方法,而不是對類進行類型提示 ,則只需提示接口。
這是一個例子。 假設您為輸入流和輸出流定義接口,如下所示:
interface OutputStream{
write($string); // Writes a string to the output.
close(); // Closes the output stream.
}
interface InputStream{
read($length); // Reads at most $length characters.
eof(); // TRUE, if the input stream is empty.
}
您現在可以創建copy
功能或方法,將流的完整輸出復制到輸入,而不需要任何輸出:
// 50 is just chosen randomly.
function copy(InputStream $input, OutputStream $output){
while(!$input->eof()){
$output->write($input->read(50));}}
恭喜,您的copy
實現現在適用於輸入和輸出流的每個組合,甚至不實現一個。
另一方面,抽象類可用於實現通用功能,而無需實現完全功能的類。
再一次,一個例子。 比方說,你想擁有輸出流。 你想要一個方法write($s)
,它將一個字符串寫入輸出,你想要一個方法writeLine($s)
,它將字符串和一個額外的換行符寫入輸出。 那么這是合適的:
abstract class AbstractOutputStream{
public function writeLine($s){
$this->write($s."\n");}}
具體的輸出流現在可以從抽象輸出流繼承,實現只需write
並免費獲得writeLine
!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.