• Advertisement
Sign in to follow this  

[.net] Inheritance and Scope problem with my engine... In C#

This topic is 3451 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, I'm new to oop in general (still regard 68K Asm as my favorite language) and have got myself a little stuck... [rolleyes] I'm trying to implement a dictionary collection of graphic objects. Only cBox is implemented in this sample, the use of an abstract class makes it very easy to add cCircle, cSprite, etc. The Draw() method makes a call to the parent GraphicsDevice, but of course, it is out of scope. I realise it's the Dictionary limiting the scope of inheritance, but I don't know how to fix it. I've previously tried passing dxDevice as a parameter to the methods, but the code soon got messy. Unfortuneatly there's a few other things that are used globally, they're just not implemented in my sample. Any OOP gurus out there? [cool]
  class cSceneManager
  {
    private Dictionary<string, cSceneObject> dictObjects = new Dictionary<string, cSceneObject>();
    public GraphicsDevice dxDevice;

    public cSceneManager(GraphicsDevice device)
    {
      dxDevice = device;
    }

    public void Draw(string strSceneName)
    {
      foreach (cSceneObject SceneObject in dictObjects.Values)
      {
        SceneObject.Draw();
      }
    }

    public void AddBox(string name, int width, int height)
    {
      dictObjects.Add(new cBox(name, width, height);
    }
  }


  abstract class cSceneObject
  {
    public string strName;
    public abstract void Draw();
  }


  class cBox : cSceneObject 
  {
    public int intWidth;
    public int intHeight;

    public cBox(string name, int width, int height)
    {
      strName = name;
      intWidth = width;
      intHeight = height;
    }

    public override void Draw()
    {
      dXdevice.DrawBox(intWidth, intHeight);  // Out of scope!
    }
  }


[Edited by - Racky1275 on November 10, 2008 3:57:33 AM]

Share this post


Link to post
Share on other sites
Advertisement
In that exact situation I would pass dxDevice to the Draw calls inside cSceneManager's Draw function. One quick idea, in the case that multiple members are required you could put them all in a structure that could then be a member of cSceneManager. Then instead of passing them all alone pass that member to the draw functions.

Share this post


Link to post
Share on other sites
Quote:
Original post by Wolfdog
In that exact situation I would pass dxDevice to the Draw calls inside cSceneManager's Draw function. One quick idea, in the case that multiple members are required you could put them all in a structure that could then be a member of cSceneManager. Then instead of passing them all alone pass that member to the draw functions.


I'm with Wolfdog - I would make the Draw method take a structure, perhaps DrawContext, DrawParameters, etc. In it you would expose the dxDevice, which lets you make it private in the SceneManager class. By using a structure, you protect yourself from having to revisit all of the derived classes' Draw methods if you need to add additional information to the structure, like selected state, clip box, or anything.

I'm in favour of this kind of approach because it protects the manager from having to expose all of its members to the public, and instead controls when in the update loop specific subsystems and objects can be accessed. Often I have passed in a structure which actually contains only interfaces, so the client objects, like box, circle, etc, never actually see the dxDevice - instead they see an interface IDxDevice, which exposes only the properties and methods client code should ever worry about.


Share this post


Link to post
Share on other sites
Thanks for the help guys. You're right, passing a structure would be a great practical solution, but isn't there a more OOPy way of solving this problem. Maybe deriving a new type of Dictionary?

The 'reasoning' behind my obsession is that my actual engine uses a lot more layers, and you end up passing the structure quite a few times. This seemed inefficient when the code itself neatly defines a heirarchical structure, with things like dxDevice always at the top.

My graphics engine currently works, so this is more a theoretical exercise to help improve my OOP theory really. Solving the scope issue is part 1, finding a more generic way of adding cBox, cCircle, etc. was part 2. (thinking .Add(type, params...)

(I went overboard with my public's in the sample, but in practice would probably convert most of them to Protected's.)

Share this post


Link to post
Share on other sites
Passing the graphics device context into Draw calls is called Dependency Injection (providing the Draw call takes an interface, not an implementation). It's a perfectly valid way of doing things and won't contravene any OOPiness you seek.

Also, consider making your public fields private, rather than protected. This way, you can protect the data invariant in one place.

Share this post


Link to post
Share on other sites
Thanks Zdlr, I'm definately not questioning the wisdom of using DI, but this is more of a conceptual issue now... [headshake]

If your code describes a heirachical structure, then surely C# will allow you to use inheritance from top to bottom. It might not be particulary sensible in this case, but unless I can figure out how it's done then the whole concept of objects inheriting properties from parents is fairly broken.

Are we saying it is not possible with C#???

Share this post


Link to post
Share on other sites


interface ISceneObject
{
string Name
{
get;
}

IRenderContext RenderContext
{
get;
}

void Draw();
}


You could then provide concrete implementations for both the interfaces. RenderContext may be set on scene node construction and then it would have access to it during the Draw() call, without passing it through. This is also DI, just a different way around it.

Share this post


Link to post
Share on other sites
Thanks again Zdlr, but as you say, that's basically DI.

If I had a cCar class, and a cWheel class based on cCar, then cWheel could inherit the properties of cCar automatically. I could create as many cWheels as I like, but if I want to store them in a collection my inheritance is broken. I then have to start using DI to explicitly allow access to properties.

DI definately short circuits the problem, and like you say it's definately a valid technique, but there must be another way...

Sorry to be such a pain!

Share this post


Link to post
Share on other sites
A wheel inheriting from a car? Inheritance is an is-a relationship. I guess a wheel is not a car, but that a car has wheels? If you are seeking to share some properties, consider either some composition or inheriting from a third interface.

Share this post


Link to post
Share on other sites
I think you're assuming that inheritance is some sort of panacea. Generally, you should favour composition over inheritance, which is exactly what DI achieves. I'd look into evaluating your emphasis on inheritance.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement