lundi 4 juin 2018

Composition over inheritance limits

I have a number of interfaces like the following:

public interface IFoo
{
    void FooAction();
}

public interface IBar
{
    void BarAction();
}

public interface IBiz
{
    void BizAction();
}

...others...

I have also defined a base abstract implementation for my interfaces. Something like this:

public abstract class BaseFoo() : IFoo
{
    void FooAction() { ... }
}

public abstract class BaseBar() : IBar
{
    void BarAction() { ... }
}

public abstract class BaseBiz() : IBiz
{
    void BizAction() { ... }
}

... others

Now I need another number of classes that implement a subset of these interfaces. Eg:

public class FooBar : IFoo, IBar
{
    ....
}

public class FooBiz : IFoo, IBiz
{
    ....
}

public class FooBarBiz : IFoo, IBar, IBiz
{
    ....
}

In a language that supports multiple inheritance I would implement the above classes inheriting from multiple abstract classes: Eg:

public class FooBar : BaseFoo, BaseBar, IFoo, IBar
{
    ....
}

public class FooBiz : BaseFoo, BaseBiz IFoo, IBiz
{
    ....
}

public class FooBarBiz : BaseFoo, BaseBar, BaseBiz, IFoo, IBar, IBiz
{
    ....
}

but this is not allowed in C#, since this kind of inheritnce is not supported.

To achieve the same result I think the approach here is to use composition over inheritance and define the classes in the following manner:

public class FooBar : IFoo, IBar
{
    private readonly BaseFoo Foo { get; set; } // not abstract now
    private readonly BaseBar bar { get; set; } // not abstract now

    FooBar(IFoo foo, IBar bar) // Dependency injected here
    {
        Foo = foo;
        Bar = bar;
    }

    void FooAction()
    {
        Foo.FooAction();
    }

    void BarAction()
    {
        Bar.BarAction();
    }
}

First of all: is this pattern correct? A thing that makes me think something here smells is that composition over inheritance hides protected properties and field of the base classes.

Instead of composition I could also provide a base abstract class for each interfaces permutation. Eg. define a BaseFooBar, BaseFooBiz, BaseFooBarBiz, but in also in this case I find there is too much work and repetitive code.

Which is the correct approach for this kind of problem?

Aucun commentaire:

Enregistrer un commentaire