Page 1 of 1

Accessing parent objects in CLOS

Posted: Tue Jul 29, 2008 12:31 pm
by jsmcgd
I was wondering what is the best way to access the parent of an object.
Is there a way to access the parent through the child object?

For example, imagine a simple game where by if a ball is in a certain position
(eg the goal) a goal is scored and the score for that game is updated.
Imagine also that the score is dependent on the size of the ball.
So a ball of size 3 gives you 3 points.
A ball of size 8 gives you 8 points etc.

Each game object has a ball object.

Code: Select all


(defclass game ()
  (score        :initform 0 :accessor game-score)
  (game-ball    :initform (make-instance 'ball)))

(defclass ball ()
  (size :initform 1 :accessor ball-size))

(defmethod move-ball (ball x y)
  (if (ball-is-in-goal-p x y)
      <update-score>
      (move-ball-as-normal)))

It's the <update-score> part I'm having trouble with.

I realize there are various things I could do
like make the ball a global variable or make the move-ball method accept
a game object. However is there something equivalent to
ball.parent.score?

Re: Accessing parent objects in CLOS

Posted: Tue Jul 29, 2008 3:00 pm
by findinglisp
jsmcgd wrote:I was wondering what is the best way to access the parent of an object.
Is there a way to access the parent through the child object?
There is no way to do this automatically. You need to give the child a reference to its parent when it's created. Then you can access the parent through the child just like you can access the child through the parent.

Re: Accessing parent objects in CLOS

Posted: Tue Jul 29, 2008 4:38 pm
by jsmcgd
Cheers.

Is this the accepted way or should I ideally be changing my architecture so I don't run into this problem too often?

Perhaps I should get cracking on AMOP?

Re: Accessing parent objects in CLOS

Posted: Tue Jul 29, 2008 5:52 pm
by qbg
If there is only going to be one game object, you could use a global variable.

Also, in your move-ball method, I think it would be better to dispatch when the ball variable is a subtype of ball instead of T.

Re: Accessing parent objects in CLOS

Posted: Wed Jul 30, 2008 3:36 am
by jsmcgd
If I do decide to make a reference to the game object in the ball object,
how would one do this? Without a concept like this like you would
have in Java *shudder* how would you pass a reference to a parent object
to a child object when you haven't finished instantiating the parent object?

Use a factory or something? Its beginning to seem a bit kludgesque.

Re: Accessing parent objects in CLOS

Posted: Wed Jul 30, 2008 5:19 am
by Kompottkin
jsmcgd wrote:Without a concept like this like you would
have in Java ...
But there is such a concept:

Code: Select all

(defclass game ()
  ((score        :initform 0 :accessor game-score)
   (game-ball    :accessor game-ball)))

(defmethod initialize-instance :after ((game game) &rest args)
  (declare (ignore args))
  (with-slots (game-ball) game
    (setq game-ball (make-instance 'ball :game game)))
initialize-instance's first argument sure looks a lot like a this reference to me. Yes, :initform is convenient, but it works for a certain class of special cases only. For more general needs, there's nothing wrong about adding a method to initialize-instance, i.e. defining a constructor as you would in Java.

Re: Accessing parent objects in CLOS

Posted: Mon Aug 04, 2008 4:39 pm
by dlweinreb
There isn't any built-in CLOS concept of "parent" or "child" in the
sense in which you mean it. If your model is that there are games and
balls, and there's a one-to-one relationship between them, you's model
that using slots. The game would have a slot set to the ball object,
and vice versa. Then move-ball would access its "game" slot, using an
:accessor (or :reader, or with-slots, whatever), to get its hands on
the game object.

Re: Accessing parent objects in CLOS

Posted: Thu Aug 07, 2008 4:24 pm
by Exolon
jsmcgd wrote:I realize there are various things I could do
like make the ball a global variable or make the move-ball method accept
a game object. However is there something equivalent to
ball.parent.score?
This isn't really possible... when you say 'parent', I think you just mean 'client' - by using the ball, the game class is a client of the ball class. But remember that any number of different objects can share a reference to the same ball. So if there was such a thing as ball.clients, it would return a set of objects which refer to the ball. Which isn't very helpful, of course. :)
What's usually done (at least in Java, C++ and the like, since I don't have experience with CLOS yet) is for the game to either pass a reference to 'this' (which doesn't seem to exist in CLOS?) to the ball, or perhaps to register a callback function defined by the game class with the ball object that should be called on certain events.