Question

I came across a posting where it is said that MustBeCalled() method will get called if we have the Abstract class do the calling in this manner.

public abstract class AbstractClass
{
    public void PerformThisFunction()
    {
        MustBeCalled();
        AbstractMethod();
    }

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }

    //could also be public if desired
    protected abstract void AbstractMethod();
}

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

But how does MustBeCalled() method get called? In what order things are called here?

Was it helpful?

Solution

If you call PerformFunction() first, then everything will execute in the intended order, where that order is specified in the order of the lines of code in PerformFunction(). If you call AbstractMethod() directly, there's no guarantee that MustBeCalled() will ever be called. However, I notice that you have AbstractMethod() marked as protected, which means that outside consumers of your class will not be able to call it directly. They'll have to use PerformFunction() -- this is good, as there is now only one public way to invoke your internal methods, and that way guarantees the order that you need.

In truth, there is a level at which you can only guarantee that things happen by choosing to write code to make them happen. You can't, for example, guarantee that code is going to implement a game of Tetris except by actually writing that code and choosing to implement it in such a way that it produces Tetris behavior. The type system and the public/protected/private modifiers can help some by preventing some misuse (as your internals are not accessible and thus cannot be invoked by consumers of your module), but they can only go so far. This is such a case.

OTHER TIPS

You cannot enforce how an implementation to call a method when invoked. The implementation could do its own thing entirely, or do nothing.

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        // this is a perfectly valid implementation
    }
}    

A better implementation could be.

public abstract class AbstractClass
{
    public void PerformThisFunction()
    {
        MustBeCalled();
        AbstractMethod();
    }

    private void MustBeCalled()
    {

    }

    protected virtual void AbstractMethod()
    {
        MustBeCalled();
    }
}

This way refactoring tools will at least create the desired boilerplate code:

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        base.AbstractMethod();
    }
}   

However, the person overriding AbstractMethod still needs to call base.AbstractMethod, this is not enforced by the compiler at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top