正在寻找从子类隐藏抽象继承方法的其他方法
本文关键字:方法 继承 其他 抽象 隐藏 寻找 子类 | 更新日期: 2023-09-27 18:04:08
我希望从最终子类ConcreteExecutablePlugin
隐藏继承的方法Invoke()
。
整体情况:
public abstract class PluginBase
{
public abstract void Invoke(IDictionary parameters);
}
public abstract class JobPlugin : PluginBase
{
protected void CheckParameter(){//....}
public bool IsActive(){//....}
}
public class ConcreteJobPlugin : JobPlugin
{
public override void Invoke(IDictionary parameters){//...}
}
public abstract class ExecutableJobPlugin : JobPlugin
{
protected abstract void Initialize(IDictionary parameters);
public sealed override void Invoke(IDictionary parameters)
{
//final realization of Invoke() method
}
}
public class ConcreteExecutablePlugin : ExecutableJobPlugin
{
//here i want method Invoke() has been already hiden
//!!!OR use base.Invoke() better?
protected override void Initialize(IDictionary parameters)
{
//concrete plugin initialization
}
}
我只找到了一个解决方案。现在,我使用密封。你觉得这个解决方案怎么样?
你知道隐藏抽象继承方法的其他方法吗?
Re:可见性
公共方法表示设计意图,即它对所有人都可见-如果这不是设计意图,则相应地更改方法的可见性,例如protected
(但显然任何子类都有访问权限(,或者如果允许使用Invoke
的所有类都在同一程序集中,则Invoke
可以声明为protected internal abstract
。
Re:密封
根据Lasse的观点,sealed override
方法在继承过程中会破坏多态的virtual / override
链,但它仍然不能改变基方法是公共的这一事实。但是,将sealed
应用于一个类将阻止其他类全部继承,从而限制对所有受保护方法的访问。
解决方案
我认为潜在的问题与过度使用继承有关——似乎你想继承功能以获得重用,但同时需要在链中的某个点限制对"不可信"子类的访问。除了制作方法internal
+将所有"值得信赖"的子类移动到基类程序集中之外,在使用完整的子类链时,您几乎没有控制权。
我相信,通过接口解耦层次结构,并应用组合而非继承的原则,将更好地实现您的目标。事实上,装饰图案在这里看起来是一个选择。
您还可以通过将"最后一个可信任"子类(ExecutableJobPlugin
(设置为sealed
*来设置"可信度"边界。
示例:
// Expose just what is visible to your final Subclass on the interface
public interface IExecutableJobPlugin
{
bool IsActive { get; set; }
void CheckParameter();
void Initialize(IDictionary parameters);
}
// Sealed will prevent other classes from inheriting this class.
public sealed class ExecutableJobPlugin : JobPlugin, IExecutableJobPlugin
{
// Default implementation. NB, not abstract
public void Initialize(IDictionary parameters) {}
// This isn't visible on the interface
protected override sealed void Invoke(IDictionary parameters)
{
//final realization of Invoke() method
}
}
public class ConcreteExecutablePlugin : IExecutableJobPlugin
{
// Compose a decoupled IExecutableJobPlugin instead of direct inheritance
private readonly IExecutableJobPlugin _wrappedJobPlugin;
public ConcreteExecutablePlugin(IExecutableJobPlugin wrapped)
{
_wrappedJobPlugin = wrapped;
}
// Invoke() isn't on the interface so cannot be accessed here
public void Initialize(IDictionary parameters)
{
// Call 'super' if needed.
_wrappedJobPlugin.Initialize(parameters);
//concrete plugin initialization code here ...
}
public bool IsActive
{
get { return _wrappedJobPlugin.IsActive; }
set { _wrappedJobPlugin.IsActive = value; }
}
public void CheckParameter()
{
_wrappedJobPlugin.CheckParameter();
}
}
票据
- 因为
ConcreteExecutablePlugin
不再是PluginBase
的子类,所以如果将方法PluginBase.Invoke
更改为protected
,则ConcreteExecutablePlugin
将无法访问它(除了反射等技巧( - composed(née base(类
ExecutableJobPlugin
所需的所有"重用"方法和属性都需要在ConcreteExecutablePlugin
中重新布线。虽然有些乏味,但它确实允许额外的拦截,例如日志记录等交叉问题 ExecutableJobPlugin
类可能不再是抽象的,因为组合需要一个实例才能工作- 理想情况下,
ExecutableJobPlugin
应该从外部注入(而不是从内部注入new
( - 通过接口解耦可以提高类层次结构的可测试性
- 然而,
*
密封ExecutableJobPlugin
不会阻止其他人对PluginBase
和JobPlugin
等公共超类进行子类化。为了防止这种情况,您可以将所有基类保留在同一个程序集中,并将它们标记为internal
,或者继续应用接口去耦/装饰器模式,而不是在整个链上继承
这种模式显然可以在类层次结构的多个级别上重复,并且应该应用接口分离原则来确保接口保持精简和集中。
在派生类中隐藏公共方法是不可能的。public
的全部意义在于,该方法在基类和该类的任何子类中都是可访问的。
您可以尝试使用protected
,然后在派生插件中使用类似Initialize
的public
方法,也可以尝试使用internal
(尽管这可能不太可取(。