views:

399

answers:

5

Hello folks, a question about class design. Currently I have the following structure:

abstract Base Repository Class

Default Repository implementation class (implements some abstract methods, where logic is common thru all of the Specific classes but leaves other empty)

Specific Repository implementation Class (implements what is left empty in the above Default class)

I've now came to the problem where I have a specific Update() method in Specific class but when all the code in this method executes some code from the base Default class should be executed too.

I could do it like this

public override Update()
{
    // do Specific class actions and updates
    // ....

    // follow with base.Update()
    base.Update();
}

but this requires those base.XYZ() calls in all the inherited methods. Could I go around that somehow with partials?

So the requirement is to have code in both parent and inherited class (or to make those two one class using partials) and code from method implementation in both places should be executed. Also what about if I wanted to turn it around and execute base class code first followed by the inherited class code?

thanks

+2  A: 

All the partial keyword means is that the definition of the class is split between source files:

It is possible to split the definition of a class or a struct, an interface or a method over two or more source files. Each source file contains a section of the type or method definition, and all parts are combined when the application is compiled.

There still has to be a complete definition of the class in the project.

You'd be better off creating a subclass, that way you can override specific methods.

As far as partial methods go (from the same link as above):

A partial method declaration consists of two parts: the definition, and the implementation. These may be in separate parts of a partial class, or in the same part. If there is no implementation declaration, then the compiler optimizes away both the defining declaration and all calls to the method.

// Definition in file1.cs
partial void onNameChanged();

// Implementation in file2.cs
partial void onNameChanged()
{
  // method body
}

You can't have half the method in one file and the other half in another.

ChrisF
I understand it is split across multiple files but I don't understand the order in which the code is executed. That is, in case we have partial class with a partial method implemented in two files, how do these two combine together?
mare
+2  A: 

Here's how you can do this:

public sealed override void Update()
{
    UpdateCore();
    base.Update();
}

public abstract /* or virtual */ void UpdateCore()
{
    // Class-specific stuff
}
Anton Gogolev
+4  A: 

Have you considered something like:

public abstract class YourBaseClass
{
    public void Update()
    {
        // Do some stuff
        //

        // Invoke inherited class's  method
        UpdateCore();
    }

    protected abstract void UpdateCore();
}

public class YourChildClass : YourBaseClass
{
     protected override void UpdateCore()
     {
         //Do the important stuff
     }
}


//Somewhere else in code:
var ycc = new YourChildClass();
ycc.Update();
klausbyskov
this is it. I just hope it is good design, hmm..
mare
Whether or not it's good design can always be argued. But it gets the job done and is widely used by MS in the .net framework.
klausbyskov
+1  A: 

Forget about partial, that has entirely different semantics. Whether the overrider of your virtual base class method should call the base class method is not automatic. It needs to be part of your documentation. A good example are the OnXxxx() methods in the Control class, the MSDN library docs have a "Note to implementer" comment that warns that calling the base class method is usually necessary.

If you make the base class method abstract then it is crystal-clear to the overrider. If it is not, you are dropping a strong hint that it ought to be done. If you expect the override to completely replace your base implementation then you should really consider making it abstract. This ambiguity, combined with the odds that the overrider breaks your base class by overriding incorrectly, is definitely one of the weak points of polymorphism.

Hans Passant
A: 

Add a new virtual (not abstract, since not all specific implementation need to override it?) method to your Default implementation to accommodate inheritors having their own additional steps on top of it's own implementation.

Call the virtual method at the appropriate point in the Default Implementation's abstract method implementation.

You've left your abstract class as it is and transparently grown the flexibility of the default implementation.

Andras Zoltan