gpt4 book ai didi

c# - 寻找其他方法来隐藏子类的抽象继承方法?

转载 作者:太空宇宙 更新时间:2023-11-03 10:26:07 24 4
gpt4 key购买 nike

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

我只找到了一种解决方案。现在,我为此使用密封。您如何看待这个解决方案?

你知道另一种隐藏抽象继承方法的方法吗?

最佳答案

回复:可见性

公共(public)方法表明它对所有人可见的设计意图 - 如果这不是设计意图,请相应地更改方法的可见性,例如protected(但显然任何子类都可以访问),或者如果允许使用 Invoke 的所有类都在同一个程序集中,那么 Invoke 可以被声明为protected internal abstract

回复:密封

按照 Lasse 的观点,sealed override 方法会在继承过程中破坏多态的 virtual/override 链,但是,它仍然不能改 rebase 方法是民众。但是,将 sealed 应用于一个类将阻止其他类继承它,从而限制对所有 protected 方法的访问。

解决方案

我认为潜在的问题与过度使用继承有关 - 似乎您想继承功能以获得重用,但同时需要在链中的某个点将访问限制为“不可信”子类。除了使方法成为 internal + 将所有“值得信赖的”子类移动到基类程序集中这一点之外,您在使用完整的子类链时将几乎没有控制权。

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

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

关于c# - 寻找其他方法来隐藏子类的抽象继承方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31567335/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com