簡體   English   中英

C# - 我應該使用什么,接口,抽象類或兩者?

[英]C# - What should I use, an Interface, Abstract class, or Both?

因此,假設我在C#中構建某種房地產應用程序。 對於每種類型的屬性,我將創建一個類,如ResidentialProperty和CommercialProperty。 這兩個類以及所有其他屬性類將共享一些常見屬性,例如Id,Title,Description和Address信息。

我希望能做的是:
a)返回僅包含基本信息的對象集合
b)能夠調用一個方法,如GetProperty(id),它將創建並返回ResidentialProperty或CommercialProperty,或者調用GetProperties(),它將返回一個或另一個或兩者的集合。

所以說,創建一個名為BasicProperty(或PropertyBase)的抽象類可能是有意義的,它包含所有常見屬性,並且從中擴展了ResidentialProperty和CommercialProperty。 這將解決問題#1,因為我可以創建一個返回BasicProperties集合的方法。

但對於#2,能夠返回一個屬性類型或另一個屬性類型,我需要一個接口(IProperty),並從它繼承Residential和Commercial類,然后讓GetProperty(id)和GetProperties()返回一個IProperty對象(或者因為它們繼承自IProperty,我可以按原樣返回它們而不是接口嗎?)?

現在,如果我應該使用接口,我該如何處理BasicProperty類?
- 我是否將其作為摘要並實現接口? 要么
- 我是否將其作為摘要保留,所有3個類都實現了接口? 要么
- 我不是將它創建為抽象,將所有基本信息放入接口,BasicProperty,ResidentialProperty和CommercialProperty都實現了接口?

在此先感謝,Carl J.

雖然我覺得定義一個開頭的界面幾乎總是一個好主意,只是因為它有助於你的代碼在未來變得靈活,聽起來在這種情況下你實際上並不要這樣做。 您的GetPropertyGetProperties方法可以使用抽象基類作為返回值。

可以這樣想:如果我有一個名為GetShape的方法GetShape辦? 它可能會返回一個Shape ,對吧? 假設Shape是一個抽象基類,一些派生類是TriangleSquareCircle等。

但是三角形一個形狀,一個正方形一個形狀,等等 - 每個都不僅僅是一個形狀,但它們仍然是形狀 因此,如果我說“給我一個形狀”並且你給我一個正方形,你就像我問的那樣做。 那里沒有有趣的生意。

這是核心底層OOP的原理中的一個:一個導出類的一個實例它的基類的一個實例; 它只是還不止於此。

從我可以收集的內容來看,你在談論兩件不同的事情。

  1. 班級結構
  2. 這些類的數據訪問

你認為你應該創建一個抽象類來包含公共屬性是正確的,這就是繼承的含義:)(除其他外)

但我不明白為什么你不能創建一個數據訪問類,它有一個方法GetProperty(id)指定一個返回類型的PropertyBase

public PropertyBase GetProperty(long id)

GetProperty的實現中,您可以構建一個ResidentialPropertyCommercialProperty (基於您想要的業務/數據庫邏輯)然后返回它,c#允許您這樣做。

也許我想念你?

HTH

編輯::

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    class DataAccessLayer
    {
        public PropertyBase GetSomething(int id)
        {
            if (id > 10)
                return new CommercialProperty();
            else
                return new ResidentialProperty();
        }

    }

    class PropertyBase { }
    class ResidentialProperty : PropertyBase { } 
    class CommercialProperty : PropertyBase { }
}

抽象類用於提供常見行為。 接口用於提供一組特定的方法和屬性,無論它們的行為如何。

如果您的ResidentialProperty和CommercialProperty提供了一些常見的行為,那么在抽象類中實現此行為並讓它們中的每一個都繼承自此類可能是有意義的。 據推測,他們也會有一些自定義行為,否則不需要子類,只需要一個PropertyType屬性來描述實例屬於哪種類型的Property就足夠了。

然后,您可以提供您認為有用的接口,IPropertyBase,IResidentialProperty和/或ICommercialProperty。 這實際上取決於您是否希望將此庫用作其他實現的基礎,這些實現可能與您的一個或多個類具有相同的接口,但與基本抽象類的行為不同。 暴露代表您的類型的接口的另一個好處是更容易模擬單元測試。

絕對不可能完全回答這個問題,因為它實際上取決於你的對象的使用方式,但我希望這個答案能為你提供一個有用的指導方針。

我認為你應該避免使用抽象類,除非你應該完全有意義。

通過聚合,使用組件可以為您的實體提供許多常見行為,您可以通過使用接口來公開此行為。

我傾向於沿着這條路走下去的原因是,一旦你有了一個抽象的基類,你就會被綁定使用它,因為你不能擁有多重繼承。

遲早,你最終會遇到一種你需要多重繼承的情況,而你卻被搞砸了。

並不是說我是強硬派,因為我們的大量代碼庫確實利用了上面的基本抽象類,但那些實現了接口,所有在這些類上生成的代碼通過接口與它們通信,所以我們可以切換如有必要,稍后可以更靈活地輸出基類。

我看到的很快就沒有差別了。 即使實現接口,也始終可以使用抽象基類。 接口不能幫助您避免代碼重復(請參閱DRY原則 ),但它不會強制您從任何特殊的東西派生,這使得它們更容易與其他基類或接口組合。

另一方面,抽象基類可以刪除一些重復,並且更容易更改基礎中的某些內容而不觸及派生類。 當您實現其他人使用的類庫時,后者非常好。 如果您更改庫中接口的內容,則該接口的所有實現都需要更改! 如果您只使用一小組開發人員實現應用程序,這可能是一個非常小的問題。 但正如其他人所說的那樣,基類迫使你從中衍生出來,然后如果出現這種需要你就無法從別的東西中衍生出來。

不要調用您的基類或接口BasicProperty或PropertyBase,只需將其稱為Property。 你不會同時擁有Property和BasicProperty嗎? 您將使用Property類或接口。

抽象類與接口幾乎相同,不同之處在於抽象類可以在字段變量中存儲狀態。 當您的屬性具有類似於存儲的地址的數據時,帶有字段的抽象類是一種方法。

現在,類的子類化是OOD的圖畫書示例之一,但是還有其他區分對象的方法,請查看裝飾器和行為模式。 只有在需要覆蓋基類的方法時才應該進行子類化。 例如,看看這個

暫無
暫無

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

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