10

I have a class: A that is a composite of a number of smaller classes, B, Cand D.

B, C, and D implement interfaces IB, IC, and ID respectively.

Since A supports all the functionality of B, C and D, A implements IB, IC and ID as well, but this unfortunately leads to a lot of re-routing in the implementation of A

Like so:

interface IB
{
    int Foo {get;}
}

public class B : IB
{
    public int Foo {get {return 5;}}
}

interface IC
{
    void Bar();
}

public class C : IC
{
    public void Bar()
    {
    }
}

interface ID
{
    string Bash{get; set;}
}

public class D: ID
{
    public string Bash {get;set;}
}

class A : IB, IC, ID
{
    private B b = new B();
    private C c = new C();
    private D d = new D();

    public int Foo {get {return b.Foo}}

    public A(string bash)
    {
        Bash = bash;
    }

    public void Bar()
    {
        c.Bar();
    }

    public string Bash
    {
         get {return d.Bash;}
         set {d.Bash = value;}
    }
}

Is there a way to get rid of any of this boilerplate redirection in A? B, C and D all implement different but common functionality, and I like that A implements IB, IC and ID because it means I can pass in Aitself as a dependency matching those interfaces, and don't have to expose the inner helper methods.

  • Could you say a little something about why you need a class A to implement IB,IC,ID? Why not just expose B C D as public? – Esben Skov Pedersen Jun 28 '15 at 6:58
  • I think my primary reason for preferring A implement IB, IC and ID is it feels more sensible to write Person.Walk() as opposed to Person.WalkHelper.Walk(), for example. – Nick Udell Jun 28 '15 at 11:44
7

What you are looking for is commonly called mixins. Sadly, C# doesn't natively support those.

There are few workarounds : one, two , three, and many more.

I actually really like the last one. The idea of using automatically generated partial class to generate the boilerplate is probably closest you can get to actually good solution :

[pMixins] is a Visual Studio plug-in that scans a solution for partial classes decorated with pMixin attributes. By marking your class partial, [pMixins] can create a code-behind file and add additional members to your class

1

Your class is doing too much, that's why you have to implement so much boilerplate. You say in the comments:

it feels more sensible to write Person.Walk() as opposed to Person.WalkHelper.Walk()

I disagree. The act of walking is likely to involve many rules and does not belong in the Person class - it belongs in a WalkingService class with a walk(IWalkable) method where Person implements IWalkable.

Always keep in mind the SOLID principles when you're writing code. The two that are most applicable here are Separation of Concerns (extract the walking code to a separate class) and Interface Segregation (split interfaces into specific tasks/functions/abilities). It sounds like you might have some of the I with your multiple interfaces but are then undoing all your good work by making one class implement them.

  • In my example the functionality is implemented in separate classes, and I have a class composed of a few of these as a way of grouping the required behaviour. None of the actual implementation exists in my larger class, it's all handled by the smaller components. Perhaps you're right though, and making those helper classes public so they can be directly interacted with is the way to go. – Nick Udell Jun 28 '15 at 23:26
  • 4
    As for the idea of a walk(IWalkable) method, I personally dislike it because then walking services become the responsibility of the caller, and not the Person, and consistency is not guaranteed. Any caller would have to know which service to use to guarantee consistency, whereas keeping it in the Person class means it has to be manually changed for walking behaviour to differ, while still allowing dependency inversion. – Nick Udell Jun 28 '15 at 23:29
1

While it doesn't reduce boilerplate in the code itself, Visual Studio 2015 now comes with a refactoring option to automatically generate the boilerplate for you.

To use this, first create your interface IExample and implementation Example. Then create your new class Composite and make it inherit IExample, but do not implement the interface.

Add a property or field of type Example to your Composite class, open the quick-actions menu on the token IExample in your Composite class file and select "Implement interface through 'Example'" where 'Example' in this case is the name of the field or property.

You should note that while Visual Studio will generate and redirect all methods and properties defined in the interface to this helper class for you, it will not redirect events as of the time this answer was posted.

-1

What you're looking for is multiple inheritance. However, neither C# nor Java have it.

You can extend B from A. This will eliminate the need for a private field for B as well as the redirecting glue. But you can only do this for one of B, C or D.

Now if you can make C inherit from B, and D from C then you only have to have A extend D... ;) -- just to be clear though, I'm not actually encouraging that in this example since there's no indication for it.

In C++ you'd be able to have A inherit from B, C, and D.

But multiple inheritance makes programs harder to reason over, and has its own problems; Further, there's often a clean way to avoid it. Still, sometimes without it, one needs to make design tradeoffs between repeating boilerplate and how the object model is exposed.

It feels a bit like you're trying to mix composition and inheritance. If this was C++, you could use a pure inheritance solution. But since it isn't I'd recommend embracing composition.

  • 2
    You can have multiple inheritance using interfaces in both java and c#, just as the op has done in his example code. – Robert Harvey Jun 28 '15 at 21:45
  • Some may consider implementing an interface the same as multiple inheritance (as in say in C++). Others would disagree, because interfaces cannot present inheritable instance methods, which is what you would have if you have multiple inheritance. In C#, you can't extend multiple base classes, therefore, you can't inherit instance method implementations from multiple classes, which is why you need all the boilerplate... – Erik Eidt Jun 29 '15 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.