How can I cleanly design a parallel inheritance structure in C

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I have 2 sets of 2 classes where each pair has a super/sub-class relationship, and the orthogonal pair has a dependency relationship. What I am trying to determine is what to do with the constructors and/or bodies of the properties to keep the model as simple as possible with minimal data duplication.

Here s the structure in code:

public class Base1 {
    public List<Base2> MyBase2Things { get; set; }
    // Do things with Base2 objects
}

public class Sub1 : Base1 {
    public List<Sub2> MySub2Things { get; set; }
    // Do things with Sub2 objects and also with Base2 objects
}

public class Base2 {
    public Base1 MyBase1 { get; set; }
    // Do things with the Base1 object
}

public class Sub2 : Base2 {
    public Sub1 MySub1 { get; set; }
    // Do things with the Sub1 object
}

I have considered overriding the base properties in the sub-classes, but that doesn t fit very cleanly because the properties in the sub-classes don t have the same signature and so I would have to add properties.

I have also considered setting the base property in the sub-class constructor and set methods, but there is no way for the sub-class property to be updated if the base-class s property is updated.

What other options are there, and which is the cleanest (and why)?

Note: The above code is greatly simplified to illustrate the problem. There are additional properties and methods on the real classes, but this subset is the essence of the trouble I m having.

Answers

I agree with Yaur that generics may help. As far as your options and keeping the model simple as possible - this probably depends on the specifics like the responsibilities of your 4 classes.

Let s say you re dealing with parent/child relationships of various vehicles & vehicle parts.

Scenario 1: The inherited relationship brings in orthogonal capability.

public class ItemParent {  // formerly Base1
    public List<ItemChild> MyChildren {get; set;}
}

public class ItemChild {  // formerly Base2
    public ItemParent MyParent {get; set;}
}

public class Car : ItemParent {  // formerly Sub1
    public List<CarPart> MyParts {get; set;}
}

public class CarPart : ItemChild {  // formerly Sub2
    public Car ParentCar {get; set;}
}

Of course, Cars should specifically know about CarPart, not ItemChild. So you fall back on generics here.

public class ItemParent<T> where T : ItemChild {
    public List<T> MyChildren {get; set;}
}

public class ItemChild<T> where T : ItemParent {
    public T MyParent {get; set;}
}

public class Car : ItemParent<CarPart> {}
public class CarPart : ItemChild<Car> {}

public class Truck : ItemParent<TruckPart> {}
public class TruckPart : ItemChild<Truck> {}

You can call subclass.MyChildren[] just fine, or make a MyParts property which delegates to MyChildren.

In this example, I think the model is pretty simple due to the fact that the parent/child metaphor is pretty easy to grok. Plus, if you add Truck-TruckParts (or Household-Resident, Shape-Line, etc.) you re not really increasing the complexity.

An alternative here would be to move the parent/child "responsibility" to a collection object (possibly custom), like so:

public class ParentChildCollection<TParent, TChild> {}

public class Car {
    private ParentChildCollection<Car, CarPart> PartHierarchy;
    public List<CarPart> MyParts {get { return PartHierarchy.GetMyChildren(this); } }
}

public class CarPart {
    private ParentChildCollection<Car, CarPart> PartHierarcy;
    public Car ParentCar {get { return PartHierarchy.GetMyParent(this); }}
}

The downside here is that, while clean, Truck and Car might not share a lot of code (if that s what you were wanting).

Scenario 2: The inherited relationship is about specializing to a parallel item.

public class Car {  // formerly Base1
    public List<CarPart> MyParts {get; set;}
}

public class CarPart {  // formerly Base2
    public Car MyParent {get; set;}
}

public class Truck : Car {  // formerly Sub1
    public List<TruckPart> MyParts {get; set;}
}

public class TruckPart : CarPart {  // formerly Sub2
    public Truck MyParent {get; set;}
}

In this case, Truck and Car do share more code. But this starts running into signature problems that aren t easily solved even with generics. Here, I d consider making the base class more generic (Vehicle-VehiclePart). Or consider refactoring this second scenario into the first scenario. Or use the collection for parent/child management and the inheritance stictly for Car-Truck code consolidation.

At any rate, I m not really sure that either scenario matches your case. At least some factor are based on how you have (and how you can) arrange your relationships.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/6045832/how-can-i-cleanly-design-a-parallel-inheritance-structure-in-c

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils