t3chb0t
t3chb0t

Reputation: 18636

Call the same overridden method one after another in multiple classes

I have one base class C1 that provides a default implementation of a couple of methods as C2 and a lot of custom implementations Cx (+20) which looks like this:

abstract class C1
{
    public abstract void M1();
}

abstract class C2 : C1
{
    // other overridden members ...

    // M1(); has no default implementation yet.
}

class Cx : C2
{
    public override void M1()
    {
        // ...
    }
}

Now, I'd like to chain C2.M1 and Cx.M1 because I need to add a new common functionality. Usually I would create a new abstract method and call it by the second base class like this:

abstract class C1
{
    public abstract void M1();
}

abstract class C2 : C1
{   
    // M1 should get a default implementation 
    // and then M1 in the next derived class should be called
    public override void M1()
    {
        // ...
        M1Internal();
    }

    protected abstract void M1Internal();
}

class Cx : C2
{
    protected override void M1Internal()
    {
        // ...
    }
}

However, I have over 20 such classes and updating them all is a lot of work so I was wondering if there is another way that would allow me to override M1 in both C2 and Cx and call them in this order C1.M1() then Cx.M1() without creating the new intermediate helper method. Is there any better pattern for such cases?

Upvotes: 1

Views: 791

Answers (2)

Slava Utesinov
Slava Utesinov

Reputation: 13488

What about simply calling base.M1 at Cx.M1?

class Cx : C2
{
    protected override void M1()
    {
        base.M1();//i.e. C2.M1()
        //Cx.M1 internal logic
    }
}

Upvotes: 1

Adassko
Adassko

Reputation: 5343

I think it's best to use decorator pattern in this case. Use composition rather than inheritance if possible.

abstract class C1
{
    public abstract void M1();
}

class Cx : C1
{
    public override void M1()
    {
        // ...
    }
}

class CxWithCommonBehavior : C1
{
    C1 realObject;

    public CxWithCommonBehavior(C1 realObject)
    {
        this.realObject = realObject;
    }

    public override void M1()
    {
        // common behavior
        realObject.M1();
    }
}

Note than you need only one CxWithCommonBehavior class for all derived Cx classes - you pass the decorated instance in the constructor.

This way you can add more behaviors, chain them in all possible ways and even add or remove them at runtime

Upvotes: 3

Related Questions