我有一个包含辅助方法的基类。如何强制继承类调用此帮助器方法?有没有办法警告消费者必须调用GenerateId?我应该将这个帮助方法作为基础构造函数逻辑的一部分吗?
例如:
public class FooBar
{
public int GenerateId(string productCode)
{
//..some logic to return an integer;
}
}
public class AnotherFooBar : FooBar
{
public void Save()
{
var fooBarId = this.GenerateId("myproduct");
//fooBarId will be used in this code block
}
}
答案 0 :(得分:4)
您可以这样做:
public abstract class FooBar
{
public void Save()
{
var fooBarId = this.GenerateId("myproduct");
SaveCore(fooBarId);
//fooBarId will be used in this code block
}
protected abstact void SaveCore(int id);
}
现在强制子类在调用Save时调用该方法。我不知道SaveCore是否需要id,如果是,你可以将它作为样本中的参数传递。
之后,如果不需要,您可以将GenerateId设为私有,因为它看起来似乎不是您希望让人们可以自由做的事情。
无论如何,请考虑很好地记录SaveCore和id代表什么,因为继承会增加实现的复杂性,并且子类可能以错误的方式实现。
答案 1 :(得分:3)
您可以使基类抽象化并强制派生类实现方法。放置必须在基类中调用GenerateId()
的方法,并让它调用抽象方法:
public abstract class FooBar
{
protected abstract string Product { get; }
private int GenerateId(string productCode)
{
//..some logic to return an integer;
}
public void Save()
{
var fooBarId = this.GenerateId(Product);
SaveInternal(fooBarId);
}
protected abstract void SaveInternal(int id);
}
public class AnotherFooBar : FooBar
{
protected override string Product { get { return "myproduct"; } }
protected override void SaveInternal(int id)
{
// id will be used in this code block
}
}
此外,由于派生类可能希望为不同的产品生成ID,因此也要在基类中创建一个抽象的只读Product
属性,从而强制派生类提供产品名称。
答案 2 :(得分:2)
您无法在重写方法上“强制执行”任何操作。你是从错误的角度看待这个。
请参阅Martin Fowler's Article有关正确方法的信息。
基本上,如果您的基类需要在每次调用覆盖时执行特定代码,那么您应该只覆盖基本方法的“部分”,如下所示:
class A
{
void MethodOne()
{
//Here you perform your obligatory logic.
//Then, call the overridable logic.
MethodOneCore();
}
virtual void MethodOneCore()
{
//Here you perform overridable logic.
}
}
class B: A
{
override void MethodOneCore()
{
//Here you override the "core" logic, while keeping the obligatory logic intact.
}
}
答案 3 :(得分:0)
这是你要找的吗? (你的问题不完全清楚......)
public class FooBar
{
public abstract int GenerateId(string productCode);
public void Save()
{
var fooBarId = this.GenerateId("myproduct");
//fooBarId will be used in this code block
}
}
public class AnotherFooBar : FooBar
{
public override int GenerateId(string productCode)
{
//..some logic to return an integer;
}
}