PDA

View Full Version : Child-Parent interaction


Impacatus
04-03-2010, 07:44 PM
I read somewhere on these forums that it wasn't good object oriented practice to have a child class reference its parent directly. I thought about it, and it makes sense, since it makes the program less organized and the two classes less modular.

But then what do I do if a child class needs to alter or access a parent variable? As far as I can tell, I have basically two options:
1. Pass the child a pointer to any variables it might need at the start of the program.
2. Let the child store any changes it wants to make as a variable and set the parent to constantly check for these change requests.

Of these two, I like the first better, but are there other ways? What's considered best practice in this situation?

wvxvw
04-04-2010, 12:18 AM
I'd say neither :)
Events (or callbacks) - this is what makes relationship between any objects "anonimous". So, you'd add a listener to the child from parent at the point when child-parent relaionship is established, and then, once the child needs to tell something to the parent, the child would dispatch an event. The parent then would handle the event and reset it's property.
Or, in the callback scenario - the parent would pass a callback to the child and the child would call the callback once it needs to reset the parent's property.

Impacatus
04-04-2010, 04:12 AM
Hmm, ok thanks. I know about automatic events like mouse events or keyboard events and the like, but I don't understand how to manually fire off an event. Could you link me a a good tutorial on this?

Also, I can see how that would work for setting or altering values, but what about retrieving values? Events wouldn't provide an immediate response, would they?

ASWC
04-04-2010, 04:57 AM
the way to do this is quite simple once you've seen it or understand it.

The parent class creates or has a reference to the child (quite normal).

The parent class add an event listener to the child (so we are still in the parent class here).

In the event handler the parent runs some code using the public properties and method of the child (e.currentTarget as ...myChildClass). That's how you would retrieve values since the event target would be the child, you will have total access to the child properties inside the even handler.

All this happens inside the parent class and can work with built in events and of course custom events as well.

Impacatus
04-04-2010, 06:11 AM
Hmm ok, it seems to kind of defeat the purpose of not having the classes reference each other. I guess it's a little better since the referencing only goes one way, and I suppose a certain amount of referencing is unavoidable.

However, I still don't fully understand. That solves the problem of the parent accessing child variables, but what if the child needs something from the parent?

For instance, what if the "cashier" class needs to know the price of a certain item in the "shop" class to complete the "transaction" function? The only way I could see would be to fire an event that asks for the price and restart the transaction based on this information, which seems over complicated to me.

Another possibility I've come across is using static properties of a class imported into multiple classes. What's the consensus on this? I wouldn't be surprised if it isn't a good idea in general, but it seems perfect for my current project.

ASWC
04-04-2010, 07:41 AM
In a typical encapsulation/OOP principle, a child would not ask or communicate directly with a parent but instead be fed with information by the parent. There might be some cases where communicating directly from child to parent can't be avoided for some reasons but in general that is poor OOP design. For example the brakes of a car should not ask the driver if he/she is currently braking. Instead the driver should push the brake pedal, the brake pedal should activate the brake circuit, the brake circuit should activate the brakes. All element know what to do and everything works from top to bottom. Now if you create a set of classes where the work flow goes from children to parents then you have created classes that are probably not very OOP friendly and hard to maintain/update.

Impacatus
04-04-2010, 09:15 AM
I can sort of understand that. Maybe I'm going about my project all wrong from the start. Maybe you or someone else can suggest a better way.

The user interface is mainly made up of three MovieClips. The problem is, there are interdependent relations between them. The first one needs data altered by the second, the second needs data altered by the first, and they both need data altered from the third. They basically all draw from and alter the same set of data.

Because of the interdepencies, I really don't see how I could easily do this in a top-down fashion.

I guess the proper way to do it would be to store the shared data in the parent class, altering it through events when necessary the passing it to the other two every time this happens? It seems far more complex and unwieldy than just letting them all reference the shared data.

Anyways, I really appreciate your explanations, thanks.

ASWC
04-04-2010, 04:12 PM
In this case maybe you need a manager type of class. This class will keep reference to your three objects and update them as needed when one object request data. I personally like to work with events so each object dispatch a custom event when it needs something to be done. The manager receive the event and request all necessary data from all needed object and then update them. Here again the object themselves are not the one driving the behavior, the manager class is.

Impacatus
04-04-2010, 06:04 PM
Ok, so if I have a button on class1 that's supposed to output the sum of variables on class2 and class3, then I would:
-Fire an event when the user clicks the button on class1
-catch the event in the manager class, and start a method that retrieves the necessary variables from class2 and class 3
-add them together, and call a method in class1 to display it?

Feasible enough, although it doesn't leave much work for any class but the manager class.

Ok, I think I get it, but I still don't understand custom events. Do you know a good tutorial?

ASWC
04-04-2010, 06:40 PM
Feasible enough, although it doesn't leave much work for any class but the manager class.That's kinda the point, you encapsulate functionality so your other classes don't have to worry about what's going on with your manager and three subclasses.

There's really not much to learn about custom events. You could create your own custom event class but simpler (at least for a start) is simply to dispatch a static string with the Event class:

each of the 3 classes dispatch an event (which can be a particular event for each class) like this (all pseudo code):

public static const CLASSONEREQUEST:String = "class one request update";


private function handleClickOfButton(e:MouseEvent):void
{
dispatchEvent(new Event(CLASSONEREQUEST));
}
//so this is in class one


same pattern for second and third class, now in the manager:

private var classoneinstance:Classone = new Classone();
//so on for class2
//so on for class3
classoneinstance.addEventListener(Classone.CLASSON EREQUEST, handleClassone);

private function handleClassone(e:Event):void
{
var classoneref:Classone = e.target as Classone;
classoneref.update(classtwoinstance.data, classthreeinstance.data);
}
just to give you an idea of how that could work.

Impacatus
04-04-2010, 07:02 PM
Alright, I think I see how it works. Thanks again. :)

wvxvw
04-04-2010, 07:14 PM
I think thats one of my favorite quotes of all times: "Do not overcook!" (Wacky Mac - macaroni and cheese pack) :)
Meaning that if all that the child has to do is to calculate two values, why not just tell the child the values? And if the values cannot be "told" to the child - then you have no choice but to move that calculation to the parent.

The reason it's been like this is that OO would anyway add some bloating - so, try to use what it adds as much as you can, otherwise it's kind of a wasted effort.

Impacatus
04-04-2010, 08:47 PM
Well, the thing is if I did it this way, I'd have one huge complex class doing all the real work, while the others just display what it tells them to. It would need to know exactly what each one of them needs as well.

I don't know, it just doesn't seem very organized. So much of the work is being done by this one class that I might as well not even have more than one class.

Maybe it will make more sense when I see it in action. I'll try it in a future project.

Thanks for all your help.

wvxvw
04-05-2010, 01:26 AM
You can always use your own judgement! If it looks like one class is doing to much - make it two classes :) There are all sorts of equipements in OO arsenal for doing that: inheritance, composition, decorators and so on. The point of OO is to make your life comfortable. But, if you don't feel comfortable with how the things are going, then you might be doing something wrong :)

Impacatus
04-05-2010, 07:12 PM
Well, thanks again, I appreciate it.

I just don't understand how using events is inherently superior to pointers or even referencing the parent. Either way, there's communication going both directions, with the disadvantages that entails. Still, I'll try to design this way as much as is convenient, maybe it will grow on me.

What's considered the right way to do it in a language that doesn't have events?

ASWC
04-05-2010, 07:19 PM
there's nothing wrong with working with references. It just a tiny bit less flexible. The advantages of events is that the children don't need to know what their parent does or what it's supposed to do since all they do is dispatching events no matter if a class will catch them or not. The advantage of this is simple, you can replace anytime the parent class by a new one (let's say version 2.0!) and that would never change a thing for the children since all they do is dispatching events. Or let's say you discover that all your code logic is wrong and you need to change it, now with all your classes with references to other classes that would be a big pain to change anything but with classes only dispatching events that would just be a matter of reorganizing.

Impacatus
04-05-2010, 07:45 PM
I guess that's true, the ability of the parent class to ignore input from the child classes is something you wouldn't have as easily through referencing the parent.

But then, couldn't you achieve a similar setup by passing references to functions to the child class? If the function reference is null, have the child not call it. This would have the benefit of getting an immediate return value rather than waiting for the event to be caught.

If the logic of your code is wrong, wouldn't you still have to do some pretty major revision of all the parent-child references, as well as in your parent class? Doesn't seem like it would be that much less work.

Like I said though, I'll keep trying. Thanks, both of you, for your patience.

wvxvw
04-05-2010, 11:43 PM
Well, what if only parent logic is wrong? :)
And, AS3 is the reference-based language, you cannot get the pointers unless you try very-very hard and mess with bytecode to alter for / switch maybe... and even then, I don't think it would be very easy to get there... :)

Now, you describe some particular to your application scheme of parent-child relationship. However, to be honest, I don't even see where would you use that in a, say, TreeMap-like class. But, from how you describe it, I'd say - no, it doesn't sound good because you are trying to put some logic into the child to handle something about it's parent, which you by all means should avoid - by doing it this way you introduce tight coupling (now, if we get back to the wrong logic, if you make the child depend on parent's logic, then, no matter if the child's logic is OK, if you screwed the parent, you screwed the child too :) ) That sounds a bit to anthropomorphic, well, I didn't to that on purpose.

cpucpu
04-06-2010, 05:35 PM
For sure, the best approach for when you have a few of classes that need to comunicate one another other at any direction is to implement an intermediate static event dispatcher class.

So a class that have to say something tell it to the dispatcher class, and classes that need to hear something listen it through the dispatcher class. :rolleyes:;)

Impacatus
04-09-2010, 08:35 PM
For sure, the best approach for when you have a few of classes that need to comunicate one another other at any direction is to implement an intermediate static event dispatcher class.

So a class that have to say something tell it to the dispatcher class, and classes that need to hear something listen it through the dispatcher class. :rolleyes:;)
Huh, I think I could have worked with that. Ah well, maybe next time.

Nevertheless, I think I'll explain my project. Everyone's been really helpful, and I'll understand if no one wants to look over this, but here it is.

It's a rewrite of one of my older projects: http://runechart.com/chinese.swf Try adding 中 if you need a word.

As you can see, there are three main movie clips, the word screen, the options screen, and the quiz screen.

The main complication is that the whole thing is centered around a huge xml dictionary, with over 45,000 entries each consisting of four fields: traditional style, simplified style, pinyin phonetics, and English translation.

Without access to this dictionary, the quiz screen can't generate questions or wrong answers for multiple choice questions, and the word screen can't search for matches of the word placed in the input box.

Without access to the setting in the options screen, the other screens don't know which part of the dictionary to output.

In order to do it in a truly top-down way, I would think:
-the options screen would send an event to the manager class. I have no problem with this.
-the word screen would send the inputted word as an event to the manager class, which would search and add the word, adjust the score, and refresh the list on the word screen using either simplified or traditional.
-the manager class would have to roll to choose which question type, roll to choose which word is correct, decide if the question needs false choices, and if so roll to generate those, decide which fields from the dictionary the question needs, and send them down to be displayed.

Several very complicated tasks all being handled by one class, especially the third, having to tailor its behavior uniquely to each of the four types of question.

It really seems like it would be much simpler if, if nothing else, all classes could access the dictionary. That way, questions could generate themselves based on minimal input from the manager class, and the word screen could be more self-contained.

Well, anyways, that's why I'm having trouble. This seems like a unique situation, and I can see how the principles you've taught me could work in general. Thanks for all your help.

wvxvw
04-10-2010, 09:20 AM
Well, I'm not really sure what your program is supposed to do, but so far you explain it, it is a classical example of MVC, where your dictionary would be the model, screens would be views and you'd need some kind of a controler to create views, feed them the data and get their feedback if they are supposed to do something apart from displaying the data. I'm not really sure where the child-parent relationship comes into play here though...
Normally, if you say child-parent relationship, you'd think of collections like trees, maps or lists. (Flash display list would be the tree kind of collection).

Impacatus
04-12-2010, 03:50 AM
That sounds about right, but I don't understand how that can be done with a strictly top-down architecture.

I guess I have a lot to learn. Are there any books or tutorials you can recommend?