Best way to code a "paired" replationship?

Personally, I avoid getting myself in situations where I need two different instances (often of separate classes) to be closely linked or paired to each other.

For example (and a prime example at that) the DisplayObject’s child/parent relationship. Personally, I would consider this to be a terrible thing. (Not sure why, but gut feeling says it’s bad)

One simple rule: Each child has a property named “parent”, and each parent is able to access it’s child (just to simplify things) using a “child” property.

This could create a lot of terrible errors if some rouge code decides to change the “parent” property of the child, and the parent has no idea. Perhaps the parent’s child property is still pointing to that old child, which is now the child of a completely different parent, ruining that relationship.

Personally, I wouldn’t even let the child know who his parent is (yes, I’m mean), and let the child run his rule independently. Yet sometimes you really need this “paired” relationship between two or more objects.

There are a few ways I have come up with to get around this, though (code examples abbreviated):

1. Only the parent holds an actual “child” variable. The child’s “parent” getter/setter really loops through all of the parents available and checks which one it belongs to. (Roles can also be reversed where the child is the only one with the actual saved value)

class Parent
{
   static var allParents:Array;

   private var _child:Child;
   public function get child():Child
   {
      return _child;
   }
   public function set child(new_child:Child):void
   {
      _child = new_child;
   }
}
class Child
{
   public function get parent():Parent
   {
      for (var i:int = 0; i < Parent.allParents.length; i++)
      {
         if (Parent.allParents*.child == this)
            { return Parent.allParents*; }
      }
   }
   public function set parent(new_parent:Parent):void
   {
      for (var i:int = 0; i < Parent.allParents.length; i++)
      {
         if (Parent.allParents*.child == this)
            { Parent.allParents*.child = null; }

         if (new_parent != null)
            { new_parent.child = this; }
      }
   }
}

2. Both the child and the parent contain references to each other, and are VERY careful to always notify and change the other object in case the value changes. NOTE: This is REALLY, REALLY dangerous if any of the getter/setters are overridden by a function that is too sloppy to make sure the other value will always be notified of changes.

class Parent
{
   private var _child:Child;
   public function get child():Child
   {
      return _child;
   }
   public function set child(new_child:Child):void
   {
      if (_child != null)
      {
         _child.parent = null;
      }

      _child = new_child;

      //Make sure that this parent value wasn't set by the child now making
      //sure that it's parent value is correct
      if ((_child != null) && (_child.parent != this))
      {
         _child.parent = this;
      }
   }
}
class Child
{
   private var _parent:Parent;
   public function get parent():Parent
   {
      return _parent;
   }
   public function set parent(new_parent:Parent):void
   {
      if (_parent != null)
      {
         _parent.child = null;
      }

      _parent = new_parent;

      //Make sure that this child value wasn't set by the parent now making
      //sure that it's child value is correct
      if ((_parent != null) && (_parent.child != this))
      {
         _parent.child = this;
      }
   }
}

3. Keep an array of all pairs of children/parents

class Parent
{
   public function get child():Child
   {
      return PC_Collection.getChild(this);
   }
   public function set child(new_child:Child):void
   {
      PC_Collection.setRelationship(this, new_child);
   }
}
class Child
{
   public function get parent():Parent
   {
      return PC_Collection.getParent(this);
   }
   public function set parent(new_parent:Parent):void
   {
      PC_Collection.setRelationship(new_parent, this);
   }
}
//Stands for Parent/Child collection.
//Was originally going to be named Child/Parent collection, but I didn't think it was the best idea...
class PC_Collection
{
   private static var collection:Array = new Array();

   public static function getParent(child:Child):Parent
   {
      for (var i:int = 0; i < collection.length; i++)
      {
         if (collection*.child == child)
            { return collection*.parent; }
      }
      //If no match, it has no parent, so return null
      return null;
   }

   public static function getChild(parent:Parent):Child
   {
      for (var i:int = 0; i < collection.length; i++)
      {
         if (collection*.child == child)
            { return collection*.parent; }
      }
      //If no match, it has no child, so return null
      return null;
   }

   public static function setRelationship(parent:Parent, child:Child):void
   {
      //Clear all relationships of the parent
      for (var p:int = 0; p < collection.length; p++)
      {
         if (collection[p].parent == parent)
         {
            collection[p].parent == null;
            collection[p].child == null;
            //TODO: Remove "[p]" from the array
         }
      }
      
      //Clear all relationships of the child
      for (var c:int = 0; c < collection.length; c++)
      {
         if (collection[c].child == child)
         {
            collection[c].parent == null;
            collection[c].child == null;
            //TODO: Remove "[c]" from the array
         }
      }
      
      //Add a new relationship
      collection.push({parent:parent, child:child});

   }
}

My question is, what is the best way? What am I supposed to do?

[SIZE=1]Perhaps I’m just paranoid, and dream all night about rouge code destroying relationships and secretly changing variables. :cantlook: Am I the only one that lives my life with this constant fear? The funniest part is that I’m actually serious…
[/SIZE]