19

I feel like I skipped a C# class or two, but here's my dilemma:

I have an abstract class from which I derive multiple child classes.

I know for sure that for each of the child classes I will have a constructor that needs a certain static object as a model and this object will be different for each of the child classes.

My first approach was to make a public static object in the abstract parent class and then, before I start creating any instances of the child classes, I would modify it for each of them, but it turns out that this way I actually make only ONE static object, for the abstract class, and each of it's child classes uses it.

How could I solve the problem?

To be more exact, here is the pseudocode:

The parent abstract class:

 abstract class AbstractClass
{
   static public ModelObject Model;
   ...
}

One of the child classes:

class Child : AbstractClass
{
    ...
    public Child()
    {
        this.someField = Model.someField;
    }
}

EDIT:

The Model needs to be a member of the "ModelObject" class, it should NOT be a singleton or anything else.

EDIT2:

To be even more exact, i chose this implementation for a game of chess: I have an abstract class for the chess pieces and the child classes represent the concrete pieces of the game: pawns, knights, et cetera.

The abstract class inherits from MeshMatObject, a class that represents generic 3d objects with the basic functionality, like rotations, meshes, materials, textures and so on and it defines abstract methods for chess game pieces, like GetPossibleMoves().

The Model object I was talking about above is a member of the MeshMatObject and, in my opinion, should be defined outside the class just once and then used for all the pieces. I mean: for example all the pawns have the same mesh and texture, so I don't see the point of giving a model as a parameter every time you want to make a pawn.

cantrem
  • 616
  • 2
  • 8
  • 20
  • 2
    In which way does AbstractClass need to access the Model? – dtb Aug 22 '10 at 16:04
  • 2
    You should consider passing a Model instance to your subclasses' constructors instead of using such a static field. – Trillian Aug 22 '10 at 16:11
  • I agree with Trillian. Having the static model is really violating the spirit of encapsulation here. – Kirk Woll Aug 22 '10 at 16:22
  • @dtb: The abstract class doesn't actually need to access the model. The child classes need to access it within their constructors @Trillian: yes, that would be a solution and actually it was my first implementation, but since all the objects of the class are build after the same exact model, I thought it should be better to define the model only once inside the class and use the static field to construct new instances. – cantrem Aug 22 '10 at 17:55
  • Why does it need to be static? Do you share state between all classes? – Jordão Aug 22 '10 at 18:06
  • @Jordão: Um, I share the Model between all OBJECTS of the same type. – cantrem Aug 22 '10 at 20:09

3 Answers3

22

You can get around the shared static field by making your Abstract class generic. Each generic class will get it's own copy of the static fields.

abstract class AbstractClass<T>
{
   static public ModelObject Model;
   ...
}

Then each child class will use a different instance of the static field.

class Child : AbstractClass<Child>
{
    ...
    public Child()
    {
        this.someField = Model.someField;
    }
}

It doesn't matter that AbstractClass doesn't reference the generic parameter. You are only using it to give each child class a unique instance of the base class.

shf301
  • 31,086
  • 2
  • 52
  • 86
  • 1
    Thanks for the input, it's halfway there. The other half comes from Justin R. If I would have used just your solution, I would have had no way of operating with just AbstractClass objects. For example, I would have had a hard time laying out a 2D array of abstract chess pieces. Anyway, it's very good to know that with generic classes every child receives a copy of the static field. – cantrem Aug 22 '10 at 19:58
9

I tend to use something similar to @shf301's solution. Depending on your needs it may useful to setup the base class as:

abstract class AbstractClass
{
}

abstract class AbstractClass<TModel> : AbstractClass
    where TModel : ModelObject 
{
   static public TModel Model;
   ...
}

This allows me a common base class that I can work with in non-generic functions. This also allows derived types to choose the exact model type and can cut down on casting.

Justin R
  • 371
  • 2
  • 9
  • 1
    It works perfect! Just that the "..." are on "AbstractClass". A nice and simple implementation, thanks. One more thing: is there any performance penalty or such with this implementation? I don't see any reason why it should be, especially with the "optimize code" feature of VS, but just making sure. – cantrem Aug 22 '10 at 20:05
  • EDIT: In my case the type constrain should be AbstractClass; then the child classes would be declared as shf301 points out. This is because I need the implementation just for AbstractClass's children. something like: AbstractClass : AbstractClass where T : AbstractClass and the child: ChildClass : AbstractClass – cantrem Aug 22 '10 at 20:21
3

How about a factory to decouple your classes from an inherited Model:

public static class ModelObjectFactory
{
    public static ModelObject GetModel<T>(T obj)
    {
        // return ModelObject according to type of parameter
    }
}

class Child
{
    public Child()
    {
        ModelObject mo = ModelObjectFactory(this);
        this.someField = mo.someField;
    }
}
devio
  • 36,858
  • 7
  • 80
  • 143
  • A factory would have worked better in other cases. In this particular one I think I would have over-complicated (if that's a word) the situation; but thanks for the idea! – cantrem Aug 22 '10 at 19:59
  • Having objects with a single responsibility never complicates things. Check SOLID principles. -1 to the comment if that was possible :) – Ignacio Soler Garcia Jan 19 '18 at 10:11