Dev*_*inB 5 c# inheritance-prevention
我有一个具体的基类Foo,包含30个与其子类相关的方法.
现在我遇到了一个仅针对基类的情况,我想创建一个无法继承的方法,这可能吗?
Class Foo
{
/* ... inheritable methods ... */
/* non-inheritable method */
public bool FooSpecificMethod()
{
return true;
}
}
Class Bar : Foo
{
/* Bar specific methods */
}
var bar = new Bar();
bar.FooSpecificMethod(); /* is there any way to get this to throw compiler error */
Run Code Online (Sandbox Code Playgroud)
编辑
我不确定我最初是否清楚.
我理解继承的原则,我理解Liskov替代原则.在这种情况下,只有一个例外处理"未继承"的情况,所以我不想创建一个'uninheritedFoo'子类.
我问在技术上是否可能创建一个foo.FooSpecificMethod()是有效且可公开访问的方法的情况,但是subclassoffoo.FooSpecificMethod()会抛出编译器错误.
基本上我想在一个未密封的课上使用密封方法.
Ree*_*sey 11
我会重新考虑这个需要.
如果你使用继承,你建议"Bar"是"Foo".如果"Bar"始终是"Foo",那么处理"Foo"的方法也应该适用于"Bar".
如果不是这种情况,我会将其作为私有方法重做.公开地,Bar应该永远是Foo.
只是为了更进一步 -
如果你能做到这一点,事情会变得非常复杂.您可能遇到以下情况:
Foo myBar = new Bar(); // This is legal
myBar.FooSpecificMethod(); // What should this do?
// It's declared a Foo, but is acutally a Bar
Run Code Online (Sandbox Code Playgroud)
但是,您实际上可以使用反射来强制执行此行为.我认为这是一个坏主意,但是FooSpecificMethod()可以检查它的类型,如果它不是typeof(Foo),则抛出异常.这将是非常混乱,并有一个非常难闻的气味.
编辑以回答问题的编辑:
编译器无法强制执行您的要求.如果你真的想强制编译器检查这个,并防止这种情况,你真的应该考虑让Foo成为一个密封的类.在这种情况下,您可以使用其他扩展方法而不是子类化.
例如,您可能希望考虑使用事件或委托来扩展行为,而不是允许对象成为子类.
试图做你正在完成的事情基本上是试图阻止继承的主要目标.
Brian对Liskov Substitution(upmodded)说得对.而里德对"is-a"(也是修改版)的正确态度; 事实上,他们都在告诉你同样的事情.
您的公共方法是与您的类Foo的用户签订的合同,说"您可以随时"在Foo上调用这些方法.
对Foo进行子类化意味着您说在可以使用Foo的地方使用子类(例如Bar)总是可以接受的.特别是,它意味着你没有(必然)继承Foo的实现(你可以覆盖它,或者Foo可能是抽象的,并且没有为方法提供特定的实现).
实现的继承(如果有的话)是一个细节; 你真正继承的是公共接口,契约,对用户的承诺,就像Foo一样可以使用Bar.
实际上,他们甚至可能都不知道他们有一个Bar,而不是Foo:如果我创建了一个FooFactory,并且我写了它的Foo*getAFoo()来返回一个指向Bar的指针,他们可能永远不会知道,并且不必知道.
当您违反该合同时,您将中断对象方向.(而Java Collection类,通过抛出NotSupported异常,完全破坏OO - 用户不能再多态地使用所谓的子类.这是糟糕的,糟糕的设计,这给许多Java用户造成了很大的麻烦,而不是模仿的东西. )
如果有一个Foo子类不能使用的公共方法,那么该方法不应该在Foo中,它应该在Foo子类中,而其他子类应该从Foo派生.
现在,这并不意味着Foo中的所有方法都应该在子类上可调用.不,我不是在反驳自己.非公共方法不是类的公共接口的一部分.
如果您希望Foo中的方法无法在Bar上调用,并且不应在Foo中公开调用,则将该方法设为私有或受保护.