views:

2448

answers:

7

My question is pertaining to the best practice for accessing a child object's parent. So let's say a class instantiates another class, that class instance is now referenced with an object. From that child object, what is the best way to reference back to the parent object? Currently I know of a couple ways that I use often, but I'm not sure if A) there is a better way to do it or B) which of them is the better practice

The first method is to use getDefinitionByName, which would not instantiate that class, but allow access to anything inside of it that was publicly declared.

_class:Class = getDefinitionByName("com.site.Class") as Class;

And then reference that variable based on its parent to child hierarchy.
Example, if the child is attempting to reference a class that's two levels up from itself:

_class(parent.parent).function();

This seems to work fine, but you are required to know the level at which the child is at compared to the level of the parent you are attempting to access.

I can also get the following statement to trace out [object ClassName] into Flash's output.

trace(Class);

I'm not 100% on the implementation of that line, I haven't persued it as a way to reference an object outside of the current object I'm in.

Another method I've seen used is to simply pass a reference to this into the class object you are creating and just catch it with a constructor argument

var class:Class = new Class(this);

and then in the Class file

public function Class(objectRef:Object) {
    _parentRef = objectRef;
}

That reference also requires you to step back up using the child to parent hierarchy though.

I could also import that class, and then use the direct filepath to reference a method inside of that class, regardless of its the parent or not.

import com.site.Class;
com.site.Class.method();

Of course there the parent to child relationship is irrelevant because I'm accessing the method or property directly through the imported class.

I just feel like I'm missing something really obvious here. I'm basically looking for confirmation if these are the correct ways to reference the parent, and if so which is the most ideal, or am I over-looking something else?

Thanks in advance for taking the time to help a newbie out!

+1  A: 

I've always used your second method, passing a pointer to the parent object to the child and storing that pointer in a member variable in the child class. To me that seems to be the simplest method for the child to communicate back to the parent.

dagorym
+3  A: 

It's generally good to have the class as it's own instance and reduce tight coupling to something else (as in this case, it's parent). If you do something like parent.doSomething() it's not possible to use that class in container that doesn't have the doSometing() method. I think it's definitely better to pass in whatever the class may need and then inside the class it doesn't have to do any parent.parent etc anymore.

With this if you in the future want to change the structure, it's very easy to just pass in a new reference; the implementation of the child class doesn't have to change at all.

The third alternative you have here is also very different, it's accessing a class level static method (you don't have to type the whole class path when accessing that method), not an instance method as in the first two.

Antti
Yea for the third alternative I mention that since I'm importing the class there isn't a parent to child relationship, Thanks!
vanhornRF
+1  A: 

I like to pass the parent as an interface (so the class can be contained in any parent implementing that interface) or implement the reference as an event/function pointer/delegate which the parent can hook onto.

Nick
A: 

Thanks for the input, I've generally been leaning more to the passing reference to the child with a constructor argument, just wanted to see if there were any alternatives floating around that anyone else had found.

vanhornRF
+1  A: 

I like setting up a global class to handle references to classes that need to be accessed by any other class, not necessarily the child.

The global class simply consists of static getters and setters like so:

private static const class:Class;

public static function setClass(_class:Class){
class = _class;
}
public static function getClass(void):Class{
return class;
}

The nice thing about this is that you don't have to import the class you are returning from the global class, just the global class itself.

The class that needs to be referenced adds itself to the global list. The Other cool thing is that you can easily dispatch events from this centralized location.

Most of the time if a class needs to be referenced by child classes or any other class, i do it through an interface.

With the global class you are describing above, if it's in the same package folder as the classes accessing it, you shouldn't even have to import that either, it should be accessible with something like ClassName.setClass(Class);
vanhornRF
+4  A: 

In general, if you need a child to communicate with a parent, you should look at having it do so by broadcasting events. This decouples the child for the parent, and makes it possible to have other classes work with the child.

I would not recommend passing in a reference to the parent class into the child.

Here is a a simple example (I have tested / compiled this so there may be some typos).

//Child.as
package
{
 import flash.events.EventDispatcher;
 import flash.events.Event;

 public class Child extends EventDispatcher
 {
  public function doSomething():void
  {
   var e:Event = new Event(Event.COMPLETE);
   dispatchEvent(e);
  }

  public function foo():void
  {
   trace("foo");
  }
 }
}


//Parent.as
package
{
 import flash.display.Sprite;
 import flash.events.Event;
 public class Parent extends Sprite
 {
  private var child:Child;
  public function Parent():void
  {
   c = new Child();
   c.addEventListener(Event.COMPLETE, onComplete);
   c.foo();//traces foo

   c.doSomething()
  }

  public function onComplete(e:Event):void
  {
   trace("Child broadcast Event.COMPLETE");
  }

 }
}

In most cases, you would dispatch custom events and pass data with them.

Basically:

Parent has reference to Child and communicates via method calls. Child does not have reference to Parent, and communicates (to anyone) via dispatching events.

hope that helps...

mike chambers

[email protected]

mikechambers
A: 

If these objects are in the DisplayList, then you have some more options. If I have a ParentClass and a ChildClass, in the child class, you seem to be able to access the parent if you cast the request as the ParentClass. e.g.

ParentClass(parent).parentFunction();

I know for sure it works if the ParentClass is the Document Class. As the Document Class is always the first item in the display list, this works:

ParentClass(stage.getChildAt(0)).parentFunction();

In my case, they were both members of the same package, so I did not even need to import anything. I haven't tested it in all circumstances, but it worked when I needed it to.

Of course 'parent' and 'getChild...' only work if these objects are in the DisplayList, but that's been good enough for me.