-1

Please consider the attached figure.

What I want is that the (technical-) "User" can use methods from class A, B or C by an instantiate of "HeadClass". What I try to avoid is, that I have to add a separate function for each method defined in Class A, B and C to call them through the "HeadClass". I tried to describe this in an other stackoverflow-request yesterday but have deleted it because it seemed to be unclear what I wanted to achieve. So here is an other approach.

Usually this would be achieved by inheritance (if only one class would be inherited from). But, as they told me in that deleted post, I should use Interface instead. Now, so far I thought that I know how interface work (using almost for every class), but I can't figure how I achieve this describe problem.

How would I have to fill the "???" in "HeadClass"? I am happy for any input. Thx in adavnce!

The Problem

class User
{
    public User(IHeadClass headObj)
    {
        _headObj = headObj
    }

    public DoStuff()
    {
        _headObj.Method_1
        _headObj.Method_2
        _headObj.HeadMethod
    }
    
    
}


public class HeadClass : IHeadClass, ???
{
    ???

    public HeadClass( ??? )
    {
        ???
    }

    void HeadMethod()
    {
        ... do head stuff
    }
}


public class Class_A : IClass_A
{
    public void Method_1 () { }
}


public class Class_B : IClass_B
{
    public void Method_2 () { }     
    public void Method_3 () { }
}

public class Class_C : IClass_C
{
    public void Method_4 () { }
}

I have check out this describing how to use interfaces instead. But this doesn't solve the above problem.

RadioMan85
  • 337
  • 1
  • 11
  • Holy moly. A "-1" without feedback! How dare you! May I ask you to provide either a feedback describing why you gave me that "-1" or remove it again and don't look at this post again. I try to not ask stupide questions, sometimes it is not easy to ask the correct question and sometimes questions are not simple either but complex. So, why the "-1"? – RadioMan85 Mar 26 '21 at 13:00

3 Answers3

1

If I understand correctly you can use composition here. Something like this:

public interface IClass_A
{
    void Method_1 ();
}

public interface IClass_B
{
    void Method_2 ();
    void Method_3 ();
}

public interface IClass_C
{
    void Method_4 ();
}


public interface IHeadClass : IClass_A, IClass_B, IClass_C
{
    void HeadMethod();
}

public class HeadClass : IHeadClass
{
    private readonly IClass_A _a;
    private readonly IClass_B _b;
    private readonly IClass_C _c;

    public HeadClass(IClass_A a, IClass_B b, IClass_C c)
    {
        _a = a;
        _b = b;
        _c = c;
    }

    void HeadMethod()
    {
        ... do head stuff
    }

    public void Method_1() => _a.Method_1();

    public void Method_2() =>  _b.Method_2();
    public void Method_3() =>  _b.Method_3();

    public void Method_4() => _c.Method_4();
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Yes, almost. I just wished to get rid of the method linking public void Method_1() => _a.Method_1(); Or is this probably the minimum possible? – RadioMan85 Mar 26 '21 at 12:34
  • 1
    @RadioMan85 you can try using default interface methods for this (which personally I would not do and also depends on actual implementation) but except for that I don't know many options. It looks like you want something like traits/mixins which are not a part of C#. – Guru Stron Mar 26 '21 at 12:36
  • It seems like I want something like traits/mixins (didn't know these words yet). – RadioMan85 Mar 26 '21 at 13:02
1

C# (unlike for example C++ or PHP) does not support multiple inheritance. Interfaces allows multiple inheritance, but they don't provide definitions of methods, only declarations.

I think solution could be pattern called fasade: write methods in HeadClass that calls methods in other classes. In this case interfaces are not necessary.

public class HeadClass
{
    private Class_A _a;
    private Class_B _b;
    private Class_C _c;

    public HeadClass( Class_A a, Class_B b, Class_C c )
    {
        _a=a;
        _b=b;
        _c=c;
    }

    void HeadMethod()
    {
        ... do head stuff
    }

    public void Method_1 () {
        _a.Method_1();
    }
    public void Method_2 () {
        _b.Method_2();
    }
    public void Method_3 () {
        _b.Method_3();
    }
    public void Method_4 () {
        _c.Method_4();
    }

}
  • Yep, this is my current approach which I don't like because of that superfluous code, in my opinion. But I guess I have to choose in between these two solutions. Thx for your input. – RadioMan85 Mar 26 '21 at 13:04
0

May I suggest instead that you have an interface passed instead of Class definition in your constructor?

public class HeadClass
{
    private IMethod1 _method1;
    private IMethod2 _method2;
    private IMethod3 _method3;
    private IMethod4 _method4;

    public HeadClass( IMethod1 method1, IMethod2 method2, IMethod3 method3, IMethod4 method4)
    {
        _method1=method1;
        _method2=method2;
        _method3=method3;
        _method4=method4;
    }

    void HeadMethod()
    {
        ... do head stuff
    }

    public void Method_1 () {
        _method1.Method_1();
    }
    public void Method_2 () {
        IMethod2.Method_2();
    }
    public void Method_3 () {
        IMethod3.Method_3();
    }
    public void Method_4 () {
        IMethod4.Method_4();
    }

}

Now you have removed any direct coupling to a class, you are no only linked by interface.

Say you want to split method 2 and 3 into it's own two classes? this code, never has to change.

You can now reuse any class that has a definition of the interface, as a paramater. No code is defined twice, that does the same thing, in each input.

Because:

public class Method1 : IMethod1
{

}

public class Method2 : IMethod2
{

}

public class Method3 : IMethod3
{

}

public class Method4 : IMethod4
{

}

can now be parsed as parameters to HeadClass.

or, if you insist method 2 & 3 belong on the same class.

public class ClassA: IMethod1
{

}

public class ClassB: IMethod2, IMethod3
{

}

public class ClassC: IMethod4
{

}

Should be obvious from this example that the benefits lie in the fact that you can now do whatever you want in Headclass, and if you need behaviour to change, you can inject code via constructor, without having to retry the behaviour of headclass.

And headclass, doesn't know ClassA, B or C exist directly, only the interface.

I Believe this is called the Strategy pattern?

Morten Bork
  • 1,413
  • 11
  • 23