Thursday, April 28, 2011

C# polymorphism once again - virtual properties

Hello, This time I have problem with virtual fields.

I have core class for my game objects. This class contains a field with Model class object. Model's object contains values such as position etc.

Now - while drawing I need to read position of each object from it's model. The problem starts when instead of default model class I'm using derived. Example:

abstract class GenericGameObject { public DefaultGameObjectModel Model = new DefaultGameObjectModel(); }
class Plane : GenericGameObject { public void shoot(Missile m){ m.Model.Position.X = 10; } }
class Missile : GenericGameObject { public new MissileModel Model = new MissileModel(); }

class DefaultGameObjectModel { public Vector2 Position = new Vector2(){X=0}; }
class MissileModel : DefaultGameObjectModel { }

Plane p = new Plane();
Missile m = new Missile();
p.shoot(m);
// NOT OK! ((GenericGameObject)m).Model.Position.X == 0

I tried to make Model defined as virtual property instead of field, but this fails because derived properties have to be of same type as their base. Casting is futile because there will be many other model types. What can I do if I want to read a value from derived class, not from base?

From stackoverflow
  • It sounds like your GenericGameObject needs to be a generic type, where the type parameter derives from DefaultGameObjectModel:

    abstract class GenericGameObject<TModel>
        where TModel : DefaultGameObjectModel
    {
         private TModel model;
    
         // Or whatever
         public TModel Model
         {
             get { return model; }
             protected set { model = value; }
         }
    }
    
    Ziell : It seems to be good answer for my question, I have but one more issue - the type of game object requires exact type of model, and now I can use any type I'd like to while creating an object. Also, MissileModel could contain extra methods which wouldn't be seen in Missile without casting :/
    Jon Skeet : I think you've misunderstood. You could still have a Missile type, which would derive from GenericGameObject. Then you'd still be able to see MissileModel methods because the model is strongly typed.
  • You could also create an IGameObjectModel interface and then implement it in each of your Object Model classes. Your GameObject would then have an instance of IGameObjectModel.

    Ziell : I'd like the idea, but base class would contain some code which is shared in all derived class (moving, rotating etc). I would break the DRY rule in that case.
    Justin Niessner : Your base classes could still inherit from the DefaultGameObjectModel class and have it's own implementation of the interface.
    Ziell : In that case you're right of course. I think it would be strange to have both Base class and Interface for same thing :) But it can be solved that way

0 comments:

Post a Comment