[英]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.