[主要编辑,我的第一篇文章有点误导。我的抱歉]
给出如下课程:
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静态函数。
答案 0 :(得分:4)
递归通用:
public class BankAccount<T> where T : BankAccount<T>, new()
{
public T SomeFactoryMethod() { return new T(); }
}
public class SavingsAccount: BankAccount<SavingsAccount>{}
您注意到我使工厂方法非静态,因为静态方法不会被继承。
答案 1 :(得分:2)
您无法完全按照定义问题的方式执行此操作。解决这个问题的最佳方法是将您的工厂完全赶出课堂:
public class BankAccount
{
}
public class SavingsAccount : BankAccount
{
}
public static class BankAccountFactory
{
public static T Create<T>() where T : BankAccount, new()
{
return new T();
}
}
现在Factory不依赖于实际类型。您可以传递BankAccount的任何派生类并在不做任何额外工作的情况下将其取回,或者担心继承您的工厂方法。
答案 2 :(得分:1)
如果可以,我想扩展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>
{
}
答案 3 :(得分:0)
为了使用继承,您需要一个对象的实例和该对象的成员。在这种情况下,对于对象我们不能使用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 */ }
对于你的问题的简单回答:你不需要使用泛型或类似的东西,你只需要你的方法不是静态的......