正在寻找从子类隐藏抽象继承方法的其他方法

本文关键字:方法 继承 其他 抽象 隐藏 寻找 子类 | 更新日期: 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不会阻止其他人对PluginBaseJobPlugin等公共超类进行子类化。为了防止这种情况,您可以将所有基类保留在同一个程序集中,并将它们标记为internal,或者继续应用接口去耦/装饰器模式,而不是在整个链上继承

这种模式显然可以在类层次结构的多个级别上重复,并且应该应用接口分离原则来确保接口保持精简和集中。

在派生类中隐藏公共方法是不可能的。public的全部意义在于,该方法在基类该类的任何子类中都是可访问的。

您可以尝试使用protected,然后在派生插件中使用类似Initializepublic方法,也可以尝试使用internal(尽管这可能不太可取(。