我希望从最终的子类Invoke()
中隐藏继承的方法ConcreteExecutablePlugin
。
全局:
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
}
}
我找到了一个解决方案。现在,我正在使用密封件。您对此解决方案有何看法?
你知道隐藏抽象继承方法的其他方法吗?
答案 0 :(得分:2)
回复:可见性
公共方法表示所有人都可以看到的设计意图 - 如果这不是设计意图,则相应地改变方法的可见性,例如: protected
(但显然任何子类都有访问权限),或者如果允许使用Invoke
的所有类都在同一个程序集中,则Invoke
可以声明为protected internal abstract
。< / p>
Re:密封
根据Lasse的观点,sealed override
方法会在继承期间破坏多态virtual / override
链,但它仍然无法改变基本方法是公共的这一事实。但是,将sealed
应用于类将阻止其他类继承所有类,从而限制对所有受保护方法的访问。
<强>解决方案强>
我认为潜在的问题与过度使用继承有关 - 似乎您希望继承功能以获得重用,但同时需要将链中某个点的访问限制为“不值得信任的“子类。除了让方法internal
+将所有“值得信赖的”子类移动到基类程序集中之外,在使用完整的子类链时,您几乎无法控制。
我认为通过接口解耦您的层次结构,并应用composition over inheritance的原则,将更好地实现您的目标。事实上,Decorator pattern似乎是一个选择。
您还可以通过将“最后值得信赖”的子类(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
将无法访问它(除了像反射这样的黑客。)ExecutableJobPlugin
所需的所有“重用”方法和属性需要在ConcreteExecutablePlugin
中重新连接。虽然有点单调乏味,但它确实允许额外的拦截,例如交叉问题,如伐木。ExecutableJobPlugin
类可能不再是抽象的,因为组合需要一个实例才能工作。ExecutableJobPlugin
应在外部注入(而不是new
内)*
密封ExecutableJobPlugin
不会阻止其他人继承公共超类,如PluginBase
和JobPlugin
。为了防止这种情况,您可以将所有基类保留在同一个程序集中,并将它们标记为internal
,或者继续在整个链中应用接口解耦/装饰器模式而不是继承。对于您的类层次结构的多个级别,显然可以重复该模式,并且应该应用interface segregation principle以确保您的接口保持精简和专注。
答案 1 :(得分:0)
在派生类中隐藏公共方法是不可能的。 optimize for unknown
的重点是该方法可以在基类和中访问该类的任何后代。
您可以尝试使用public
,然后在派生的插件中使用protected
方法,例如public
,或者您可以尝试使用Initialize
(尽管可能不可取的。)