寻找其他方法从子类隐藏抽象继承方法?

时间:2015-07-22 15:18:57

标签: c# oop inheritance override abstract

我希望从最终的子类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
     }
}

我找到了一个解决方案。现在,我正在使用密封件。您对此解决方案有何看法?

你知道隐藏抽象继承方法的其他方法吗?

2 个答案:

答案 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将无法访问它(除了像反射这样的黑客。)
  • 组合(néebase)类ExecutableJobPlugin所需的所有“重用”方法和属性需要在ConcreteExecutablePlugin中重新连接。虽然有点单调乏味,但它确实允许额外的拦截,例如交叉问题,如伐木。
  • ExecutableJobPlugin类可能不再是抽象的,因为组合需要一个实例才能工作。
  • 理想情况下,ExecutableJobPlugin应在外部注入(而不是new内)
  • 通过接口解耦可提高类层次结构的可测试性
  • *密封ExecutableJobPlugin不会阻止其他人继承公共超类,如PluginBaseJobPlugin。为了防止这种情况,您可以将所有基类保留在同一个程序集中,并将它们标记为internal,或者继续在整个链中应用接口解耦/装饰器模式而不是继承。

对于您的类层次结构的多个级别,显然可以重复该模式,并且应该应用interface segregation principle以确保您的接口保持精简和专注。

答案 1 :(得分:0)

在派生类中隐藏公共方法是不可能的。 optimize for unknown的重点是该方法可以在基类中访问该类的任何后代。

您可以尝试使用public,然后在派生的插件中使用protected方法,例如public,或者您可以尝试使用Initialize(尽管可能不可取的。)