user89010
user89010

Reputation: 43

I would like to override a method in C#, but I have a different signature

The base class user should access the original method

class A
 public init()

The derived class user should aceess ONLY the derived method.

class B
 public init(int info)

I cannot use "override" bc there's a different signature. What options do I have so that the derived class user does not see two methods.

Notes. All in all I just need two classes that share some code. Inheritance is not a must. But simplicity for the user of B is a priority.

Upvotes: 4

Views: 6641

Answers (8)

Mathieu Garstecki
Mathieu Garstecki

Reputation: 1629

There is no perfect solution here. Some possible ways to do it:

An approach would be to make A.Init() virtual, override it in B and make it throw a NotImplementedException/InvalidOperationException.

Init() stays visible, but the user finds out very quickly that it is not to be used (make it explicit that Init(int info) is to be used in the XML documentation and in the message of the exception).

If you don't care about the inheritance part and just want to use the functionalities of class A in class B, don't have B deriving from A and make B instantiate A and use its functionalities.

Edit: You can use an interface implementing the common operations in order to retain inheritance while avoiding to implement Init() in B:

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
}

This can be made even better by using a factory:

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;
    }
}

This way instantiation code is well encapsulated, the difference between the two Init() methods is hidden from the user code.

Upvotes: 0

jason
jason

Reputation: 241641

This is a big code smell (and violates some basic OOP tenets) and, to the best of my knowledge, can not be done in any language. In OOP, an instance of B is an instance of A; this is polymorphism. So if A has a public method named init accepting no parameters, then so does B.

What are you trying to do this for?

Edit: Now that you've added the edit that states that inheritance is not a must, just use composition to share code. Give B a private instance of A, for example.

Upvotes: 10

n8wrl
n8wrl

Reputation: 19765

Presumabely A and B have something in common. Can you factor that out into a different base class?

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

if you need polymorphism then references to Base or, better yet, Thomas' interface are the way to go.

Upvotes: 1

Daniel Earwicker
Daniel Earwicker

Reputation: 116674

Contrary to some answers/comments here, what you are asking for would have a real use if it existed:

class Derived : Base
{

This can be seen by considering the workaround:

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

In other words, it's not really a base class at all, but a hidden part of the implementation.

The downside with this workaround is: what Base has an abstract method that you have to supply? You have to write this:

class Derived
{
    class ActualDerived : Base
    {
        // override abstract method(s)
    }

    private Base _base = new ActualDerived();

This is the whole point of private inheritance (as found in C++) - it's for situations when you want to inherit the implementation but not the "interface" (in the informal sense).

But in C#, it's not available.

Upvotes: 1

Omu
Omu

Reputation: 71198

it looks like it's not yet possible

i tried to do something like this:

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

    public void Init(int x)
    { }
}

but Init() it's still visible from the A class

Upvotes: 0

Yuliy
Yuliy

Reputation: 17718

What you're asking for is impossible, due to the nature of the type system. Any instance of B can be thought of as an A, so you can call any of A's methods (including Init()). The best you can do is overload Init() in B and throw an exception to catch this at runtime.

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

Upvotes: 1

Emil Ivanov
Emil Ivanov

Reputation: 37633

According to the Liskov principle you simply cannot do that, because it would violate this principle. The best thing you can to is override init() in the derived class and make it throw an exception every time it's invoked, stating that the user should use init(int info) and rely on the test to catch the errors.

Why you can't simple replace the init() method or even make it protected?

The Liskov principle states (rephrased) that where an instance of class A is required, an isntance of class B extends A can be passed. If a method expects A and wants to call init() on it and you pass B (which extends A) to it with a protected init() the method will fail. This is the reason why the code will not even compile.

Upvotes: 5

Tomas Aschan
Tomas Aschan

Reputation: 60574

Instead of inheritance, use an interface as a "middle man":

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
    }
}

Upvotes: 0

Related Questions