1

I'm trying to call a function in one child class (Circle.as) from another child class (Wedge.as). Circle.as is instantiated by the document class (Tree.as), and Wedge.as is instantiated by Circle.as. How do I do this? This is my code:

Tree.as

package com.treediagram  
{  
  public class Tree extends MovieClip  
  {
    var firstCircle:Circle = new Circle();
    addChild(firstCircle);
  }
}

Circle.as:

package com.treediagram
{
  public class Circle extends MovieClip  
  {
    private var wedge:Wedge;
    public function Circle()  
    {
      var circleHolder:MovieClip = new MovieClip();
      var circleClip:MovieClip = new MovieClip();
      circleClip.addEventListener(MouseEvent.CLICK,circleClickedEvent);
    }

    private function circleClickedEvent(e:MouseEvent):void
    {
      var wedgeHolder:MovieClip = new MovieClip();
  circleHolderRef.addChildAt(wedgeHolder,1);
      var wedge:Wedge = new Wedge(wedgeHolderRef);
  wedge.addEventListener(MouseEvent.CLICK,wedgeClickEvent);
    }



    private function wedgeClickEvent(e.target){
      trace ('click'); //NOT WORKING
    } 
  }
}

Wedge.as

package com.treediagram
{
  public class Wedge extends MovieClip  
  {
    public function Wedge(wedgeHolderRef)
    {
      var wedgeClip:MovieClip = new MovieClip();
      wedgeClip.addEventListener(Event.ADDED_TO_STAGE, wedgeAddedEvent);
      wedgeHolderRef.addChild(wedgeClip);
    }
  }
}

I saw a similar question to this here:

How to call a function in a Class from another Class?

but it was a bit hard to follow as it relates to my problem. One of the solutions worked, but was commented as being bad form, and another did not work, so I want to make sure I structure my code properly.

Community
  • 1
  • 1
mheavers
  • 29,530
  • 58
  • 194
  • 315

3 Answers3

2

Usually it is OK for a parent class to know about its children, but not the other way around. If you don't follow this principle, you'll end up creating Circular dependencies and end up with code that is tightly coupled and hard to maintain. The key then is to prevent a child from needing to call its parent's methods directly.

One solution is to use event-based communication. When something happens in the child class, it fires an event which a parent class may choose to handle or not.

For example:

public function Circle()  
{
  var wedge:Wedge = new Wedge();
  wedge.addEventListener(MouseEvent.CLICK, onWedgeClick);
}
private function onWedgeClick(e:MouseEvent) {
  deactiveCircle();
}
panupan
  • 1,212
  • 13
  • 15
  • You might want to dispatch a custom event from the Wedge class and capture that instead. So inside the "handleWedgeClick" function, just call "this.dispatchEvent(new Event("wedgeClick"));" And then listen for "wedgeClick" instead of MouseEvent.CLICK. – Glenn Dec 01 '11 at 22:33
  • @panupan - the problem is I need to listen to the click of something inside of the wedge object, not wedge itself. – mheavers Dec 02 '11 at 15:34
  • 1
    Hello, in that case you'll need to use event bubbling. This allows an event to actually "bubble up" through the view hierarchy. It's an implementation of the Responder Chain design pattern where a message gets passed along the chain (in this case a view hierarchy) giving an opportunity for each object to handle it before passing it on. Check out this simple example to get an idea: http://blog.152.org/2009/11/flash-actionscript-3-event-bubbling.html – panupan Dec 02 '11 at 19:26
  • Ah - that's the problem - I disabled bubbling (I think) with stopPropagation() - because it was carrying down eventListeners to clips nested within clips which I don't want. Thanks for the help...now to try and understand bubbling. – mheavers Dec 02 '11 at 19:53
1

Just attach the wedgeClickHandler to the wedge member from within the Circle class - it will receive the MouseEvent just fine, and it can access the private function directly.

weltraumpirat
  • 22,544
  • 5
  • 40
  • 54
  • If I do this - one, I don't really like that things related to wedges are in the circle class, and two - it's not recognizing the click actions on my wedges. The actual class builds a clip, and that clip is added to the circle - so I'm assuming I would need to reference the clip inside the class somehow right? But I'm not sure how to do this. – mheavers Dec 01 '11 at 22:12
  • @mheavers, Well your `Circle` class is instantiating a `Wedge`, it has the responsibility of managing the `Wedge` instance; it's better then having the `Wedge` tied to upwards to a `Circle`. If you want to get more complicated, interfaces and factories are a possible solution; but that might be overkill in your case? – Peter Dec 01 '11 at 22:29
  • one - you're reacting to an event from within the wedge, but you are deactivating the *circle*. It is perfectly alright to do so, as the wedge does not need to know anything about its parent class, and wedge is a member of circle anyway. two - your circle should have a `private var wedge:Wedge`, otherwise it will be discarded. Wedge, on the other hand, does not need a reference to circle, if you use event listeners. – weltraumpirat Dec 01 '11 at 22:31
  • Hey - your solution makes sense, it's just not working for me - I don't get any errors, but my listener is not registering any activity. I am revising my question to show a little more of my actual code so you can see what's going on. – mheavers Dec 01 '11 at 22:52
  • @Panupan's solution contains the correct code - don't try to make this too complicated, all you need for the click event to work is a Circle and a Wedge. Once you've understood events and listeners, you can go ahead and add more hierarchy levels, but try to keep this first task to a minimum. – weltraumpirat Dec 02 '11 at 00:32
  • The problem is I need to listen to the click of something inside of the wedge object, not wedge itself. – mheavers Dec 02 '11 at 15:34
  • That is not a problem, because MouseEvents bubble up in the display list. – weltraumpirat Dec 02 '11 at 18:55
  • I think I disabled the bubbling with stopPropagation() because Circle contains click listeners that were getting carried down to Wedge, but wedge needed to be clickable too with a different function. – mheavers Dec 02 '11 at 19:55
  • OK, then do that in a clickHandler within Wedge and dispatch a bubbling custom event "wedgeClick" instead - you can listen for this and be sure it's not from within the circle. – weltraumpirat Dec 02 '11 at 21:19
0

You cannot call Circle.deactivateCircle() because its accessibility is set to private and because your Wedge object needs to have a reference to the Circle object upon which you want to call the method.

Brian Driscoll
  • 19,373
  • 3
  • 46
  • 65
  • You're not actually using Singleton, which is good, because it's actually an anti pattern http://misko.hevery.com/2008/11/21/clean-code-talks-global-state-and-singletons/ – Amy Blankenship Dec 02 '11 at 03:19