0

I have an interface that I need to implement on a few winforms and I would like to be able to call a specific method when an object is initialized.

I know I can just explicitly call the method from the constructor of the class, but it would be very nice to be able to implicitly call this method on all classes that implement the interface.

Similar to Mixins in Pyhton.

I'm not sure if an interface is the way this should be done, or just simply inheriting from another class that calls the method in it's constructor, but every class will have it's own implementation of the method so the latter might not work.

Desired result:

interface AutoRun{
   void CodeToRun();
}

class Foo: AutoRun {
    void CodeToRun(){
        Console.WriteLine("The Code Was Ran");
    }
}
class Bar: AutoRun {
    void CodeToRun(){
        Console.WriteLine("This Other Code Was Ran");
    }
}

Foo f = new Foo(); // -> "The Code Was Ran"
Bar b = new Bar(); // -> "This Other Code Was Ran"
Bigbob556677
  • 1,805
  • 1
  • 13
  • 38

2 Answers2

2

You could use a base class. The constructor chain will always execute for every class in the inheritance chain implicitly. For method calls, it's not completely implicit, but calling base.CodeToRun() will get you whatever base implementation is in there. You can even avoid the base.CodeToRun() call if you decide you don't want it to run.

public interface IAutoRun
{
    public void CodeToRun();
}

public abstract class AutoRun : IAutoRun
{
    public AutoRun()
    {
        Console.WriteLine("Base constructor run");
    }

    public virtual void CodeToRun()
    {
        Console.WriteLine("The code was run");
    }
}

public class Foo : AutoRun
{
    public Foo()
    {
        Console.WriteLine("Derived constructor run");
    }

    public override void CodeToRun()
    {
        Console.WriteLine("Running my derived method code");
        base.CodeToRun();
    }
}
jjxtra
  • 20,415
  • 16
  • 100
  • 140
  • 2
    This is really works, but be aware of some features of calling virtual members from constructor: https://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor – Serg Dec 31 '20 at 16:15
  • No virtual calls in constructor in this example, but yes that is something to be careful of – jjxtra Dec 31 '20 at 16:26
0

An interface is just a contract. So, you cannot make it run anything. But you can always put code that must be run at object creation into a constructor. A constructor cannot be specified in an interface. But you can call a method implementing the interface in a constructor.

If you want it to happen automatically, use an abstract base class which implements this interface and calls the code to be run in its constructor. An abstract class cannot be instantiated, and abstract members must be overridden in the deriving (non abstract) classes. In a deriving class the autorun method will then run "magically" without an explicit method call.

The naming conventions in .NET tell us to start Interface names with an upper case "I".

interface IAutoRun
{
   void CodeToRun();
}

abstract class AutoRunBase : IAutoRun
{
    public AutoRunBase()
    {
        CodeToRun();
    }

    public abstract void CodeToRun();
}

Now let us implement a concrete class with an auto run functionality:

class Foo : AutoRunBase
{
    public override void CodeToRun()
    {
        Console.WriteLine("Hello World");
    }
}

Note that the AutoRunBase class (I use to append "Base" to abstract classes to mark them as such) calls the not yet implemented CodeToRun method in its constructor. Since you cannot call new on an abstract class, this is not a problem, because it will be overridden in the deriving classes.

The constructor of a base class is automatically called before the constructor of the derived class (in this case Foo has an implicitly declared default constructor).

var run = new Foo(); // Prints "Hello World" to the console.

The interface is not required to make this work, but it allows to separate the contract form the implementation.

If you do not use the interface, you can also declare CodeToRun as protected instead of public and thus disallow it to be called from outside.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • I would just add a note here that the implementer has to be aware that the abstract method will be executed before the constructor of the inheriting class is called. – Silvermind Dec 31 '20 at 18:55