我有一个类A
,它派生自类B
:
public class B
{
protected void Run() // pass data here used by all 3 Run methods
{
BeforeRun();
RunInternal();
AfterRun();
}
private void RunInternal()
{
}
private void BeforeRun()
{
}
private void AfterRun()
{
}
}
public class A : B
{
}
我可以使用最近的成就强制继承B类的用户必须调用基本方法Run()
?
在您想要的地方添加protected
,virtual
,abstract
等等,我可以根据您的建议自由进行更改。
答案 0 :(得分:4)
除了构造函数之外,您不能要求某人调用方法。但是类的行为不应该在构造函数中,也不应该从构造函数中调用。一个类不应该只是因为我们实例化它而开始做某事。当我们调用它的方法时,它应该做一些事情。
当我们设计一个类时,它通常有一个或两个方法,这是该类的主要责任。创建该类实例的人将调用这些方法中的一个或多个,因为这是该类存在的唯一原因。
您可以设计类,以便不能覆盖主要方法,而不是添加其他方法并期望其他人调用它。唯一的public
方法在基类中。被覆盖的方法不是公开的。这样基类方法总是被调用,如果你希望基类总是这样做,它总会被完成。
这样,其他类不会更改所需的基类行为。他们只是扩展它。
public abstract class TheBaseClass
{
public void DoSomething()
{
AlwaysDoThis();
InheritedClassBehavior();
}
private void AlwaysDoThis()
{
//This method in the base class always gets called.
//You don't need to explicitly require someone
//to call it.
}
protected abstract void InheritedClassBehavior();
}
public class TheInheritedClass : TheBaseClass
{
protected override void InheritedClassBehavior()
{
//The inherited class has its own behavior here.
//But this method can't be called directly because
//it's protected. Someone still has to call
//DoSomething() in the base class, so AlwaysDoThis()
//is always called.
}
}
InheritedClassBehavior
受到保护,因此无法直接调用它。调用它的唯一方法是调用DoSomething
,它将始终调用基类AlwaysDoThis()
中的方法。
InheritedClassBehavior
是abstract
,因此继承的类必须实现它。或者你可以使它virtual
- 它在基类中有一个实现,但是一个继承的类可以覆盖它。 (如果没有任何abstract
方法,则基类不需要是abstract
。如果要阻止创建基类的实例,基类只能是abstract
class,只允许创建继承的类。)
答案 1 :(得分:0)
您最好的选择是在A
中设置一个基本实现(因此将其设置为虚拟),并且只有在需要更改Run()
的行为时才在派生类中覆盖它。
除非提供了覆盖,否则调用Run()
的任何内容都将获得基本实现。你无法强制覆盖调用基础,经典的OO根本就不起作用。
你也应该小心从构造函数中调用一个虚方法--Resharper会警告你这个(因为可能会调用覆盖,这对于基本实现来说是未知的。)
但除此之外,C#中没有任何方法可以强制派生类来调用特定方法 - 派生类扩展基类,所以强迫这种行为会打破基本的OO概念。即使您将调用放入基类中的构造函数,也无法保证派生类将调用该构造函数。您可以强制基类调用派生类(使用抽象基类方法,这必须在派生类中实现),派生方法然后可以调用回基类方法;但这本身就是一种解决方法,除非一些派生类实际上要向Run()
添加一些功能,否则这实际上是浪费时间。
另一种需要考虑的方法是使用类似PostSharp的产品 - 它允许您使用方法上的属性来实现cross cutting pattern。这仍然不会强制派生类调用基本实现,但它可能是一种方便的方法来实现您想要的(交叉切割用于审计或记录模式,其中必须在调用另一个方法时调用特定方法) )。