简体   繁体   中英

C# Force method implementation in all sub-levels of inheritance and use base implementation

I have a BaseClass, which implements a method to populate itself form a different data structure. SubClasses will add their properties to the base ones. I want all sub-classes and sub-sub...classes to implement their own version of the method and call their parent class to do the same. So this is not just overriding, I want to force the implementation, but each implementation of the method has to be called, not just overridden.

Sort of like:

class BaseClass
{
 int id;
 virtual void fromDictionary(Dictionary data)
 {
   id = data["id"];
 }
}

class Derived1 : BaseClass
{
 string name;
 override void fromDictionary(Dictionary data)
 {
   name = data["name"];
   base.fromDictionary(data);
 }
}

class Derived2 : Derived1
{
 float size;
 override void fromDictionary(Dictionary data)
 {
   size = data["size"];
   base.fromDictionary(data);
 }
}

Then doing this:

Derived2 object = new Derived2();
object.fromDictionary(dictionary);

Populates all of the object's properties.

I can make the first one virtual and override in the derived ones, but that doesn't force the implementation. And making an abstract base above this base or using an interface wouldn't force ALL levels of inheritance to implement.

The ideal case would be forcing all derived classes to implement their version AND call their parent's version (or even better, have some sort of extension/overriding that automatically calls ALL implementations of the method from the instantiated object's class upwards).

How close to that can I get ?

Seeing why you need this kind of overriding I strongly believe that you should try to move this logic to a constructor because as it looks now:

Derived2 object = new Derived2();
object.fromDictionary(dictionary);

Your object will only be valid if it has a dictionary . So instead of constructing it from a dictionary using a method, you should provide a constructor which receives a dictionary as a parameter:

Derived2 object = new Derived2(dictionary);

Now you have a valid object from the beggining. There are more reasons why you should do this instead of using a method which composes your object, one as you observed is that each subclass will need to call the base method, and having this kind of constructor (assuming that you will not provide a parameterless one) will force the inheritors to call the base one.

Another advantage in using this kind of approach is that you will have a valid object form the beginning instead of making it possible for users of that classes to make invalid objects by forgetting to call the fromDictionary() method.

Thanks for the suggestions everyone, the closest I could get is:

public abstract class DAO
{
    public long id { get; set; }

    public void fromDictionary(Dictionary<string, object> obj)
    {
        //Does own part in the method
        id = (long)obj["id"];

        //Calls most derived implementation
        fromDictionaryOperation(obj); 
    }

    //Forces child to implement its part
    protected abstract void fromDictionaryOperation(Dictionary<string, object> obj);
}

//Is forced to implement its part, and the base implementation will be executed always
public class Area : DAO
{
    public string name { get; set; }
    protected override void fromDictionaryOperation(Dictionary<string, object> obj)
    {
        name = (string)obj["name"];
    }
}

//Is NOT forced to implement method, and MUST call base.fromDictionary() for all this to work properly, but is NOT FORCED TO.
public class CircularArea : Area
{
    public float radius { get; set; }
    protected override void fromDictionaryOperation(Dictionary<string, object> obj)
    {
        radius = (float)obj["radius"];
        base.fromDictionary(obj);
    }
}

So all 2nd generation classes will be fine, but subsequent sub-classes wont be forced to implement its part or call the parent implementation. Which means that if in an implementation of a sub-sub-class, the base.fromDictionary() method is not called, then all parent classes implementation, except the first/base class, will be skipped without any compiling warning or error. To force implementation at all levels, I guess I could put the abstract method in an Interface and make all classes implement the interface, which can't be forced itself, but is as close as I can think of.

If anyone knows a way to completely force ALL of them to implement the same method, that would be top notch.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM