Pavel Matuska
Pavel Matuska

Reputation: 777

Hidden calling of a function

Let's say I have two objects, Master and Slave.

Slave has a method named Init();. The thing about Init() is, that I need it to be virtual, because it contains user's initialization code, but I also need it to get called automatically when the Slave is added to Master's List. But the method must not be callable by the user, it has to be automatic.

The first thing that I tried is an event - create an event SlaveInitialized that a Slave object could handle in its OnSlaveInitialized handler. This wouldn't work though, because there's a lot of Slave objects and I have no control over the order in which they get created and need to be initialized.

The second thing that I tried is internal method - internal Init() would be called when the object is added to Master's list and all seems okay, until I realized that by doing so I cannot inherit the method in a public class.

So the third thing I did and that worked is this - I created an internal method called _Init() that simply calls a protected virtual Init(), which solved my problem.


Now I want to ask - do I just have a major strike of being stupid, because I am missing the painfully obvious solution here, or is this the way it's normally done? What is the proper way? I hope I got the point of what I'm asking across, I tried my best to explain the problem.

Thanks for any help


This is the gist of the code I now have. Its point is to have Init() invisibly and automatically called when you add any Slave object to the Master's list via Master.AddSlave();

public class Master
{
    private List<Slave> _slaves;

    public void AddSlave(Slave slave)
    {
        // Call the "hidden" init
        slave._Init();
        _slaves.Add(slave);
    }
}

public class Slave
{        
    internal void _Init()
    {
        // Call the topmost overloaded method.
        Init();
    }

    protected virtual void Init()
    {

    }
}

public class SuperSlave : Slave
{        
    protected override void Init()
    {
        // Now this method gets called automatically
        // when Master.AddSlave adds this object.
    }
}

Upvotes: 0

Views: 194

Answers (2)

Matthew
Matthew

Reputation: 25763

While this doesn't answer the question the way you might want it, however I feel this could be an approperiate solution.

I would recommend throwing an InvalidOperationException if the Init method gets called multiple times.

Description: The exception that is thrown when a method call is invalid for the object's current state.

In my opinion it should not be your responsibility to police your objects from being abused, so long as documentation is written properly, your objects properties and method names describe what they do, it should be enough for most users (developers) consuming your code to understand how it works.

For those who decide to call Init themselves and then add to the Master object, you can throw that exception so they will know that their method for using the class is incorrect.

EDIT: Naming the method OnInit might be a good idea, that way the user of the class has an indication that it should not be directly called by themselves.

Upvotes: 1

Ruben
Ruben

Reputation: 15525

As far as I can tell, there are two basic ways to do this.

  1. Like you already tried, an internal InitInternal() method that calls a protected virtual Init()
  2. A protected internal virtual Init(), which outside of your assembly automatically becomes a protected method.

Upvotes: 1

Related Questions