views:

316

answers:

4

An abstract function must be implemented by all concrete classes.

Sometimes you want to force all derivative classes to implement the abstract function, even derivatives of concrete classes.

class Base { protected abstract Base Clone(); }
class Concrete : Base { protected override Base Clone(){...}; }
class Custom : Concrete {}

I would like the compiler to tell the programmer that the class Custom needs to implement Clone(). Is there way?

+11  A: 

It's not possible for the compiler to enforce this. You might look at writing your own analysis plugin to Gendarme or FxCop to enforce such requirements.

Michael Donohue
How would the plugin distinguish between the case where you want to force the requirement on all derivatives or just the immediate ones?
Hans Malherbe
An Attribute would be the most straightforward approach -[MustImplement] or something similar.
Michael Donohue
+3  A: 

You will have to make Concrete an abstract class to enforce that.

leppie
The goal is to have a base class that is easy to extend. You do not have control over how people are going to extend your class. You may not even be around. First prize is to document the requirement in code that the compiler can enforce.
Hans Malherbe
A: 

You can check this at run-time using reflection and throw an exception to disrupt execution, wrecking havoc for "impolite" users of your library. Performance-wise that is not very wise, even though you could store a static HashSet<System.Type> in the base abstract class with all verified types.

I think your best bet is to provide clear documentation that tells any user of your code that it is deemed necessary to override the Clone() method.

Cecil Has a Name
+3  A: 

I would guess you don't really need ALL derived classes to implement the abstract method, but it definitely sounds like you have a bit of a code smell in your design.

If you don't have any functionality in the Concrete.Clone() method, then you can make your 'Concrete' class abstract as well (just be sure to change the name ;-). Leave out any reference of the Clone() method.

abstract class Base { protected abstract void Clone(); }
abstract class Concrete : Base { }
class Custom : Concrete { protected override void Clone() { /* do something */ } }

If you have some basic functionality in the Concrete.Clone() method, but need detailed information from a higher level, then break it out into it's own abstract method or property forcing a higher level implementation to supply this information.

abstract class Base { protected abstract void Clone(); }

abstract class ConcreteForDatabases : Base 
{ 
    protected abstract string CopyInsertStatemement {get;}

    protected override void Clone()
    {
     // setup db connection & command objects
     string sql = CopyInsertStatemement;
     // process the statement
     // clean up db objects
    }
}

class CustomBusinessThingy : ConcreteForDatabases 
{
    protected override string CopyInsertStatemement {get{return "insert myTable(...) select ... from myTable where ...";}}
}
John MacIntyre
I fixed my example Clone methods to return Base. When you implement object cloning using virtual Clone methods, you need *all* derivative classes to implement the abstract method.
Hans Malherbe