簡體   English   中英

C#如何使工廠方法返回子類類型

[英]C# How to make a factory method return of the subclass type

[主要編輯,我的第一篇文章有​​點誤導。 我的appologies]

鑒於如下課程:

public class DatabaseResult{
    public bool Successful;
    public string ErrorMessage;     

    //Database operation failed
    public static DatabaseResult Failed(string message) {
         return new DatabaseResult{
             Successful = true,
             ErrorMessage = message
         };
    }
}

我如何實現子類,以便我可以添加其他屬性來表示與特定操作相關的數據(例如在SELECT類型查詢的情況下為MatchedResult),而無需實現該靜態失敗函數? 如果我嘗試使用普通繼承,則返回類型將是父類。 例如:

DoThingDatabaseResult : DatabaseResult {
     public IEnumerable<object> SomeResultSet;
     public static Successful(IEnumerable<object> theResults){
          return new DoThingDatabaseResult {
               Successful = true,
               ErrorMessage = "",
               SomeResultSet = theResults
          };
     }
     //public static DatabaseResult Failed exists, but it's the parent type!
}

目標是避免需要為每個子類實現復制Failed靜態函數。

使其遞歸通用:

public class BankAccount<T> where T : BankAccount<T>, new()
{
    public T SomeFactoryMethod() { return new T(); }
}

public class SavingsAccount: BankAccount<SavingsAccount>{}

您會注意到我使工廠方法非靜態,因為靜態方法不會被繼承。

您無法完全按照定義問題的方式執行此操作。 解決這個問題的最佳方法是讓您的工廠完全脫離課堂:

public class BankAccount
{
}

public class SavingsAccount : BankAccount
{
}

public static class BankAccountFactory
{
    public static T Create<T>() where T : BankAccount, new()
    {
        return new T();
    }
}

現在工廠不依賴於實際類型。 您可以傳遞BankAccount的任何派生類,並在不做任何額外工作或擔心繼承工廠方法的情況下將其取回。

如果可以的話,我想擴展一下StriplingWarrior。 實際上,您可以為工廠使用靜態。 以下代碼顯示a和c是預期的對象類型。 限制是你不能在基類本身上使用工廠。

 private void Testit()
    {
        var a = SavingsAccount.Factory();
        var c = CheckingAccount.Factory();
        //var b = BankAccount.Factory(); //can't do this
    }


public class BankAccount<T> where T : BankAccount<T>, new()
{
    public static T Factory()
    {
        return new T();
    }
}

public class SavingsAccount : BankAccount<SavingsAccount>
{
}

public class CheckingAccount : BankAccount<CheckingAccount>
{
}

要使用繼承,您需要一個對象的實例和該對象的成員。 在這種情況下,對於對象我們不能使用BankAccount/SavingsAccount因為那時我們已經有了我們想要得到的東西。 這意味着我們需要一個實際的工廠對象,這是大多數人在談論工廠時所談論的內容。 所以如果我們把它拉到工廠並使用繼承......

public class BankAccountFactory { public virtual GetAccount() { return new BankAccount(); } }
public class SavingsAccountFactory : BankAccountFactory { public override GetAccount() { return new SavingsAccount(); } }

但是現在我們如何獲得正確類型的實例? 我們剛剛把問題推到了一層。

相反,您可能想要做的是使用某種配置來確定類型,或者將您想要的類型傳遞給方法。

public BankAccount GetAccount(AccountType type) { /* */ }

要么

public BankAccount GetAccount() { /* Access config */ }

對於你的問題的一個簡單的答案:你不需要使用泛型或類似的東西,你只需要你的方法不是靜態的...

暫無
暫無

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

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