我想在C#中覆盖一个方法,但我有一个不同的签名

基类用户应该访问原始方法

class A public init() 

派生类用户应仅使用派生方法。

 class B public init(int info) 

我不能使用“覆盖”bc有一个不同的签名。 我有什么选项,以便派生类用户看不到两个方法。

笔记。 总而言之,我只需要两个共享一些代码的类。 inheritance不是必须的。 但B的用户的简单性是优先考虑的事项。

这是一个很大的代码气味(违反了一些基本的OOP原则),据我所知,不能用任何语言来完成。 在OOP中, B的实例是A的实例; 这是多态性 。 因此,如果A有一个名为init的公共方法,不接受任何参数,那么B也是如此。

你想要做什么呢?

编辑:既然您已经添加了表明inheritance不是必须的编辑,只需使用组合来共享代码。 例如,为B的私有实例。

根据Liskov原则,你根本不能这样做,因为它违反了这个原则。 您可以做的最好的事情是覆盖派生类中的init()并使其在每次调用时抛出exception,声明用户应该使用init(int info)并依靠测试来捕获错误。

为什么你不能简单地替换init()方法甚至使它受到保护?

Liskov原则陈述(改述)在需要class A实例的情况下,可以传递class B extends A 。 如果方法需要A并希望在其上调用init()并使用protected init()B传递给它( extends A ),则该方法将失败。 这就是代码甚至无法编译的原因。

由于类型系统的性质,你所要求的是不可能的。 B的任何实例都可以被认为是A,因此您可以调用任何A的方法(包括Init() )。 您可以做的最好是在B中重载Init()并抛出exception以在运行时捕获它。

 public class B { void Init() { throw new NotSupportedException(); } } 

与此处的一些答案/评论相反,如果存在,您所要求的内容具有实际用途:

 class Derived : Base { 

通过考虑解决方法可以看出这一点:

 class Derived { private Base _base = new Base(); 

换句话说,它根本不是一个基类,而是实现的隐藏部分。

这种解决方法的缺点是:什么Base有一个你必须提供的抽象方法? 你必须这样写:

 class Derived { class ActualDerived : Base { // override abstract method(s) } private Base _base = new ActualDerived(); 

这是私有inheritance的全部要点(如C ++中所见) – 它适用于您希望inheritance实现但不是“接口”(非正式意义上)的情况。

但在C#中,它不可用。

据推测,A和B有一些共同之处。 你能把它分解成不同的基类吗?

 public class Base { ... common stuff ... } public class A : Base { public void Init() { } } public class B : Base { public void Init(int info) { } } 

如果你需要多态,那么引用Base,或者更好的是,Thomas的接口是要走的路。

而不是inheritance,使用接口作为“中间人”:

 public interface IAllThatYouNeed { public void DoSomeStuff(); } public class A : IAllThatYouNeed { public void Init() { // do stuff } } public class B : IAllThatYouNeed { public void Init(int info) { // do stuff } } 

它看起来还不可能

我试图做这样的事情:

 public class B : A { private override void Init() { } public void Init(int x) { } } 

但是Init()它仍然可以从A类中看到

这里没有完美的解决方案。 一些可行的方法:

一种方法是使A.Init()成为虚拟,在B中覆盖它并使其抛出NotImplementedException / InvalidOperationException。

Init()保持可见,但是用户很快发现它不被使用(明确表示要在XML文档和exception消息中使用Init(int info))。

如果您不关心inheritance部分并且只想在B类中使用A类的function,那么不要从A派生B并使B实例化A并使用其function。

编辑:您可以使用实现公共操作的接口来保留inheritance,同时避免在B中实现Init():

 public interface IOperations { void DoStuff(); void Foo(); } public class A : IOperations { public void Init() { // Do class A init stuff } #region IOperations Members public void DoStuff() { // ... } public void Foo() { // ... } #endregion } public class B : IOperations { A _operations = new A(); public void Init(int initData) { _operations.Init(); // Do class B init stuff } #region IOperations Members public void DoStuff() { _operations.DoStuff(); } public void Foo() { _operations.Foo(); } #endregion } 

使用工厂可以做得更好:

 public static class OperationsFactory { public static IOperations CreateOperations() { A result = new A(); result.Init(); return result; } public static IOperations CreateOperations(int initData) { B result = new B(); result.Init(initData); return result; } } 

这种方式实例化代码被很好地封装,两个Init()方法之间的差异从用户代码中隐藏。