寻找其他方法来隐藏子类的抽象继承方法?
Looking for other ways to hide abstract inheritance method from a subclass?
我希望对最终子类 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
}
}
我只找到了一种解决方案。现在,我为此使用密封。您如何看待这个解决方案?
你知道另一种隐藏抽象继承方法的方法吗?
无法在派生的 classes 中隐藏 public 方法。 public
的全部要点是该方法可以在基 class 和 class.
的任何后代中访问
您可以尝试使用 protected
,然后在派生插件中简单地使用 public
方法,例如 Initialize
,或者您可以尝试使用 internal
(尽管可能不是更可取的)。
回复:可见性
A public 方法表明它对所有人可见的设计意图 - 如果这不是设计意图,请相应地更改方法的可见性,例如protected
(但显然任何子 class 都可以访问),或者如果允许使用 Invoke
的所有 class 都在同一个程序集中,那么 Invoke
可以声明 protected internal abstract
.
回复:密封
按照 Lasse 的观点,sealed override
方法会在继承过程中破坏多态 virtual / override
链,但仍然不能改变基方法是 public 的事实。但是,将 sealed
应用于 class 将阻止其他 class 继承它,从而限制对所有受保护方法的访问。
解决方案
我认为潜在的问题与过度使用继承有关 - 看似您想继承功能以获得重用,但同时需要在某些时候限制访问"untrustworthy" subclass 的链。除了制作方法 internal
+ 将所有 "trustworthy" subclasses 移动到基础 class 程序集之外,在使用完整的 subclasses.
我认为通过 接口 解耦您的层次结构并应用 composition over inheritance, will better achieve what you are after. In fact, the Decorator pattern 的原则看起来是一种选择。
您还可以通过将 'last trustworthy' subclass (ExecutableJobPlugin
) 设为 sealed
*.
来设置 'trustworthiness' 边界
示例:
// 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
的子 class,如果您将方法 PluginBase.Invoke
更改为 protected
,那么 ConcreteExecutablePlugin
将无法访问它(除了像反射这样的黑客攻击)。
- 组合(née base)class
ExecutableJobPlugin
所需的所有 'reused' 方法和属性需要在 ConcreteExecutablePlugin
中重新连接。虽然有点乏味,但它确实允许额外的拦截,例如像日志这样的横切关注点。
ExecutableJobPlugin
class 可能不再是抽象的,因为组合工作需要一个实例。
- 理想情况下,
ExecutableJobPlugin
应该从外部注入(而不是 new
在内部注入)
- 通过接口解耦提高了 class 层次结构的可测试性
*
密封 ExecutableJobPlugin
然而不会阻止其他人从 class 继承 public superclass 像 PluginBase
和 JobPlugin
。为防止这种情况,您可以将所有基础 class 保留在同一个程序集中并将它们标记为 internal
,或者继续应用接口解耦/装饰器模式而不是在整个链中继承。
该模式显然可以在您的 class 层次结构的多个级别重复,并且应该应用 interface segregation principle 以确保您的界面保持简洁和专注。
我希望对最终子类 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
}
}
我只找到了一种解决方案。现在,我为此使用密封。您如何看待这个解决方案?
你知道另一种隐藏抽象继承方法的方法吗?
无法在派生的 classes 中隐藏 public 方法。 public
的全部要点是该方法可以在基 class 和 class.
您可以尝试使用 protected
,然后在派生插件中简单地使用 public
方法,例如 Initialize
,或者您可以尝试使用 internal
(尽管可能不是更可取的)。
回复:可见性
A public 方法表明它对所有人可见的设计意图 - 如果这不是设计意图,请相应地更改方法的可见性,例如protected
(但显然任何子 class 都可以访问),或者如果允许使用 Invoke
的所有 class 都在同一个程序集中,那么 Invoke
可以声明 protected internal abstract
.
回复:密封
按照 Lasse 的观点,sealed override
方法会在继承过程中破坏多态 virtual / override
链,但仍然不能改变基方法是 public 的事实。但是,将 sealed
应用于 class 将阻止其他 class 继承它,从而限制对所有受保护方法的访问。
解决方案
我认为潜在的问题与过度使用继承有关 - 看似您想继承功能以获得重用,但同时需要在某些时候限制访问"untrustworthy" subclass 的链。除了制作方法 internal
+ 将所有 "trustworthy" subclasses 移动到基础 class 程序集之外,在使用完整的 subclasses.
我认为通过 接口 解耦您的层次结构并应用 composition over inheritance, will better achieve what you are after. In fact, the Decorator pattern 的原则看起来是一种选择。
您还可以通过将 'last trustworthy' subclass (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
的子 class,如果您将方法PluginBase.Invoke
更改为protected
,那么ConcreteExecutablePlugin
将无法访问它(除了像反射这样的黑客攻击)。 - 组合(née base)class
ExecutableJobPlugin
所需的所有 'reused' 方法和属性需要在ConcreteExecutablePlugin
中重新连接。虽然有点乏味,但它确实允许额外的拦截,例如像日志这样的横切关注点。 ExecutableJobPlugin
class 可能不再是抽象的,因为组合工作需要一个实例。- 理想情况下,
ExecutableJobPlugin
应该从外部注入(而不是new
在内部注入) - 通过接口解耦提高了 class 层次结构的可测试性
*
密封ExecutableJobPlugin
然而不会阻止其他人从 class 继承 public superclass 像PluginBase
和JobPlugin
。为防止这种情况,您可以将所有基础 class 保留在同一个程序集中并将它们标记为internal
,或者继续应用接口解耦/装饰器模式而不是在整个链中继承。
该模式显然可以在您的 class 层次结构的多个级别重复,并且应该应用 interface segregation principle 以确保您的界面保持简洁和专注。