2

Context

When implementing a class, there's a distinction between fields that are there because they are part of what the object is and fields that are there because they are needed to implement the object.

For example, if you are implementing an ArrayList, you will have an array that isn't part of what an ArrayList is but are required into the implementation. That's the whole point of having public properties and private fields.

The problematic case

However, I'm in a kind of weird situation were the implementation is outside the class because the algorithm is interacting with a collection of that Object.

My case is a physics engine. My Body class has public properties that make sense like Velocity, Position, Size etc. However, now it starts to have properties that only make sense when used by the class World, that interacts with a collection of bodies. I have fields like CollisionShifting (how much the body is shifted by collision), Collisions, Movement (velocity * delta, needed to check for collisions) etc. and the list is growing.

The problem is the more features I implement into World, the more unintuitive fields I have to add to Body. And that's bad because anyone who want to implement the Body interface will have to implement those fields and won't know what's their purpose. As someone who implements Body (and not World), all you care about is where is your Body and how fast does it does. You also want to get notified when collisions happen but you don't want to have details like how much the body was shifted by collisions in the last frame as a property.

Possible options

So what I would like to do is having private fields per Body for the implementation of the World into the class World but I do not like the first look of this option.

I could map every Body to a class that's only purpose is to complete body into World:

Map<Body, HiddenFieldsOutOfTheModel> extraInfos;

I could do that for every field. It would be a bit more logic because I wouldn't have a weird out-of-the-model class but I feel it's just like moving the problem:

Map<Body, Vector> collisionShiftings;
Map<Body, List<Collision>> collisionsPerBody;
//etc.

This option is a bit tedious because whenever the World wants to remove a body, it has to remove it from a variable amount of Maps. Plus, I need to encapsulate the add/remove operations while without the Maps I can just leave write access to the array.

Question

I have to say I prefer the second approach but is there something better ? What is the best solution to keep the model clear and confuse the less people possible?

In short, what is the best way to have per-object private fields in a class containing a collection of these objects?

Update

It's been a while since I asked this question but I still don't have a "perfect solution". (And I'm not sure I will ever find one) For now I've taken the Map<Body, HiddenFieldsOutOfTheModel> extraInfos; option and named my HiddenFieldsOutOfTheModel class BodyState.

Winter
  • 705

2 Answers2

1

My body doesn't know where it is.

My body doesn't know how fast it is moving.

My body does know it's experiencing 1g of acceleration. But that's only because it's colliding with the chair I'm sitting on. This is ever so slightly compressing my spine and making my butt numb.

I very much like to remove from objects what they don't need to know. Sure, if I look around the room I see plenty of other objects at measurable distances and velocities from me but that's their problem.

The fancy name for where I am is called a reference frame. Every object is entitled to think of it self as being at rest. It's the reference frames that move about.

Here's an addictive little website that tries to teach this idea with a game called Relativistic Space Sheep. Not since Asteroids have I seen a better lesson about physics baked into a game.

You've already hit on the idea of separating these things but you're not sure where to put them. I like to use one reference frame to keep track of the rest. Everything is measured relative to it. Only it knows the positions and velocities. From it you can find everything else.

candied_orange
  • 119,268
0

Allow the caller to specify the fields he wants in a "template" object, then return a handle or reference to the real object. If this were c#, the caller's code would look like

class Rock : IGameObjectTemplate
{
    //Blah blah blah
}

var rock = new Rock
{
    Position = new Point(10,10),
    Mass = 100
};
var worldObject = motionEngine.CreateObject(rock);

Or if you want to make it easier, do away with the caller's object entirely, and put the necessary parameters in a factory method:

var worldObject = motionEngine.CreateRock(10, 10, 100);

This way, the engine still manages the creation and tracking of all the world objects, but the caller can also have a copy if (s)he wants. The instance that is returned can be a totally separate type with whatever fields you need, public, private, or internal.

John Wu
  • 26,955