Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring member function in interface

Firstly I am pretty new to C#. I would like to have an interface declare a member function like in the following piece of code

interface IMyInterface {
    void MyAction() {
        // do stuff depending on the output of function()
    }
    void Function();
}

here Function is pure virtual and should be implemented by children of IMyInterface. I could use an abstract class instead of an interface but then I could not inherit from other classes... Say for example that MyAction is recursiverly searching a directory for files and applying Function to any file found to make my example clear.

How to change my design in order to overcome the constraint that interfaces cannot implement classes ?

Edit : In C++ what I would do is using templates as such

template<class A>
static void MyAction(const A& a) {
    // do stuff depending on the output of A::Function()
};

class MyClass {
    void Function();
};

I was wondering if there were an elegant way to do this using interfaces in C#.

like image 990
vanna Avatar asked Jan 24 '13 21:01

vanna


4 Answers

In C# you don't have multiple inheritance. You can circumvent this limitation by using composition.

Define your interface like this (Function needs not to be defined here):

public interface IMyInterface
{
    void MyAction();
}

Declare an abstract class with an abstract Function and implementing this interface:

public abstract class MyInterfaceBase : IMyInterface
{
    public void MyAction()
    {
        // Do stuff depending on the output of Function().
        Function();
    }

    protected abstract void Function();
}

From this abstract class you can derive a concrete implementation. This is not yet your "final" class, but it will be used to compose it.

public class ConcreteMyInterface : MyInterfaceBase
{
    protected override void Function()
    {
        Console.WriteLine("hello");
    }
}

Now let's come to your "final", composed class. It will derive from SomeBaseClass and implement IMyInterface by integrating the functionality of ConcreteMyInterface:

public class SomeBaseClass
{
}

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }
}

UPDATE

In C# you can declare local classes. This comes even closer to multiple inheritance, as you can derive everything within your composing class.

public class MyComposedClass : SomeBaseClass, IMyInterface
{
    private readonly IMyInterface _myInterface = new ConcreteMyInterface();

    public void MyAction()
    {
        _myInterface.MyAction();
    }

    private class ConcreteMyInterface : MyInterfaceBase
    {
        protected override void Function()
        {
            Console.WriteLine("hello");
        }
    }
}
like image 129
Olivier Jacot-Descombes Avatar answered Sep 24 '22 17:09

Olivier Jacot-Descombes


The only way to directly handle this would be to use an abstract class, as the interface cannot contain "logic" of any form, and is merely a contract.

One alternative, however, would be to make an interface and a static class. You could then place your logic in an extension method using the interface.

public interface IMyInterface {
    void Function();
}

public static class MyInterfaceExtensions {
    public static void MyAction(this IMyInterface object)
    {
       // use object.Function() as needed
    }
}

The main disadvantages here are more types, which reduces maintainability, and a lack of discoverability.

like image 24
Reed Copsey Avatar answered Sep 20 '22 17:09

Reed Copsey


You can define MyAction as extension method:

public interface IMyInterface
{
   void Function();
}

public static class MyInterfaceExtensions
{
    public static void MyAction(this IMyInterface obj)
    {
        obj.Function();
    }
}

Example:

public class HelloWorld : IMyInterface
{
    public void Function()
    {
        Console.WriteLine("Hello World");
    }

    public static void Main(string[] args)
    {
        new HelloWorld().MyAction();
    }
} 

Output:

Hello World
like image 44
dtb Avatar answered Sep 20 '22 17:09

dtb


Interfaces can't implement any behavior they are just contracts. If you want to implement some logic while defining a contract you could use an abstract class.

like image 25
Claudio Redi Avatar answered Sep 23 '22 17:09

Claudio Redi