[英]C# hack: low level difference between interface and abstract class
這是一個關於C#基礎知識的哲學問題:我想知道完全抽象類可以模擬接口的接近程度。 假設我們有以下界面:
public interface INativeInterface
{
void PerformAction();
String Property { get; set; }
}
以下是抽象類:
public abstract class ISimulatedInterface
{
public abstract void PerformAction();
public abstract String Property { get; set; }
}
他們有很多共同點,不是嗎? 我所知道的差異是:
使用反射或類似的東西可以跳過這些限制嗎?
我意識到接口和抽象類在root中是不同的:接口聲明了“ 可以表現得像 ”的條件,抽象類 - “ 是一種 ”,但即使這似乎是如此接近以至於這些實體之間的低級別差異要討論的。 這個問題甚至可以聽起來像“你會用C ++創建一個接口”。
使用反射或類似的東西可以跳過這些限制嗎?
否。抽象類和接口是公共語言運行時級別的不同概念。 因此,在C#中既不可能,因為最終受限於CLR的邊界。
我想知道完全抽象類可以模擬接口的接近程度。
它是可行的,但需要來自底層執行環境(無論是物理的還是管理的)的支持(或“允許”)。
在過去,我設計了一種語言,完全取代接口的抽象類。 是的,它確實支持這種“接口”的多重繼承。 但是,實施的特點可能不值得付出努力。 主要的“低級差異”是繼承的抽象類的內部嵌入式實例必須保存在實現類的實例中,並且必須保持this
指針鏈。 不用說,這是一個快樂的經歷:-)
所以,如果我理解你的問題,你有兩個相關的問題。
第一個是“抽象類和接口之間有什么區別”; 第二個是,“在C#中,我可以通過使一個沒有具體方法的抽象類表現得像一個接口來繞過差異嗎?”。
第一個問題在@Todd Schiller的鏈接中得到了很好的回答。
第二個問題更復雜。
您可能可以創建構建時任務,以將所有抽象類轉換為接口而無需具體實現。 我從來沒有嘗試過 - 因為我認為這樣做沒有任何好處,還有很多很多缺點。
最大的缺點是您的代碼變得更難以調試和維護。 開發人員學習何時創建抽象類,何時創建接口; 這是一個既定的,普遍認同的成語。 在你的代碼庫上工作的新開發人員將需要學習很多新東西 - 並且引入一種思考接口和抽象類的新方法將使這個過程變得更難和更長。
在調試應用程序時,在源代碼中看到抽象類的開發人員 - 但在運行時代碼中看到它實際上是一個接口 - 可能會感到困惑,並花時間試圖弄清楚為什么會發生這種情況,而不是追查真正的錯誤。
就我所見,沒有明顯的好處。
對我來說,它真的歸結為他們的能力。 接口永遠不會為其任何操作提供實現; 它只承諾任何使用它的人都必須提供一些東西。 抽象類可以為其任何操作提供實現,這些操作可以由其子類自行決定覆蓋。 不,你永遠不可能通過反思來覆蓋這些限制,因為它們是語言本身的核心。
至於使用抽象類代替接口,它再次歸結為您需要完成的任務。 如果需要提供一些基本實現,則必須使用抽象類 - 否則,請使用接口。
您已經提到的其他一些差異。 您可以在C#中實現多個接口,但是您只能從單個類(抽象或其他)派生。
它可能是OOPS哲學背景下的熱門話題。我們知道它幾乎沒有技術差異,如接口沒有構造函數,繼承類必須實現所有方法等但我喜歡用現實世界場景來討論它。 實際上我認為接口是一個對象與其消費者之間的契約。但是抽象類不是契約,即使兩者都可以用來實現“liskov替換原則”。 我想列出現實生活中的兩種情況..
1.)想象一個繪圖應用程序,它可能包含形狀,矩形,正方形等。這里的形狀可以是抽象類或接口類型。 但是如果我需要確保我的應用程序中的每個對象在實例化時都必須具有狀態。 我無法通過接口實現此功能,因此接口無法保持對象的狀態。
2.)如果我的形狀共享共同的值(靜態值),我無法使用接口實現,所以我認為抽象類可以保持狀態和行為
但考慮到界面是一個關於行為的協議,看起來是一個真實的例子,動物和鳥類,這兩個對象都有一些相似的行為,但我們不能說它們有共同的屬性,鳥類和動物都可以走路,哭泣,吃飯,執行這些行動完全不同。 在我們的編程接口中,在您只需要協議而不需要任何狀態的情況下,它是理想的候選者。 好消息是消費者對象可以取代滿足該協議的任何其他對象,DI就是一個最好的例子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.