views:

2744

answers:

2

Hey this question is in reply to Joel Hooks's comment on an older question of mine (How to call a function in a Class from another Class?)

I was able to fix my own problem using a public static var to reference one of my Classes, so in the other class I just needed to use the this keyword so it could be called.

instance = this; // in Navigation Class
Navigation.instance.introPlayButtonClick(); // in Intro Class

Now it seems I'm not doing this in the best or purist way for OOP(can sense debate here), so I'm posing this question a 2nd time in hopes of getting this figured out correctly.

The Problem

I have 2 Classes, Intro and Navigation. There is a button created in the Intro class that needs call a function inside of the Navigation Class. I also have a CustomEvent class where I setup Custom Events. Below is the code, I've stripped out all of the unessential code relating to this problem.

The Intro Class

When the function clicked is called, it dispatches an Event that the Navigation class is listening for.


package src.display
{
import flash.events.*;
 import flash.display.*;

 // ☼ --- Imported Classes
 import src.events.CustomEvent;
 import src.model.Navigation;

 public class Intro extends Sprite 
 {
  private var playBtn:MovieClip;
  private var colorTransform:ColorTransform;

  // ☼ --- Constructor
  public function Intro():void 
  {
      this.addEventListener(Event.ADDED_TO_STAGE, init);
  }

  // ☼ --- Init
  public function init(event:Event):void 
  {
      draw();
      this.removeEventListener(Event.ADDED_TO_STAGE, init);
  }

  public function draw():void 
  {
      playBtn = new PlayThumb;
      playBtn.buttonMode = true;   
      playBtn.x = 552;   
      playBtn.y = 289;
      playBtn.alpha = 1;

      // ☼ --- add button 
      addChild(playBtn);

      // ☼ --- button listeners
      playBtn.addEventListener(MouseEvent.MOUSE_UP, clicked);
  }
  //-----------------------------------------------------
  // ☼ --- My Old Function
  /*private function clicked(e:MouseEvent):void 
  {
      Navigation.instance.introPlayButtonClick(); // Open tab1
  }*/
  //-----------------------------------------------------
  // ♦♦♦ Added to dispatch Event to JStriedl's function ♦♦♦
  private function clicked(e:MouseEvent):void 
      {
      dispatchEvent (new CustomEvent(CustomEvent.INTRO_CLICKED, {}));
      trace("Dispatch Event INTRO_CLICKED");
      }
 }
}

Navigation Class

This is the Navigation Class which contains a function that the Intro Class needs to be able to call.


package src.model 
{
import flash.events.*;
import flash.display.*;

// ☼ ---Imported  Classes
import src.display.Intro;
import src.model.Fonts;
import src.events.CustomEvent;

public class Navigation extends MovieClip //Needs MovieClip
{  
    public var intro:Intro;
    public static var instance:Navigation;

    // ☼ --- Constructor
public function Navigation()
{
    this.addEventListener(Event.ADDED_TO_STAGE, init);
}

// ☼ --- Init
public function init():void
{
    instance = this;  
    intro = new Intro;
    attachListenerForIntro(intro);
    this.removeEventListener(Event.ADDED_TO_STAGE, init);
}

// ♦♦♦ JStriedl's code ♦♦♦
public function attachListenerForIntro(introToCheckForClick:Intro)
{
    intro = introToCheckForClick;
    intro.addEventListener("introClicked", introPlayButtonClick);
}

// Function that button in Intro needs to call
public function introPlayButtonClick(e:CustomEvent):void
{    
    trace("Navigation function called from Intro");
    intro.removeEventListener("introClicked", introPlayButtonClick);
}
}
}

Issues or Errors

So far when the button is clicked nothing happens :( I'm assuming I don't have the EventListener setup correctly inside of the Navigation Class?

+1  A: 

Errr.. the only way I could think is extending your Intro class to the Navigation class in order for this to work properly.

Something like..

public class Intro extends Navigation {}
Preston
by doing thing you might encounter some functions overwriting one another so make sure the Navigation functions are protected. Also once everything is extended correctly you can just call "super" when referencing your Navigation class from the Intro class.
Preston
Was just about to ask, I got: Overriding a function that is not marked for override. Error. So all my Navigation functions should be protected? Super is a keyword I've seen, but not sure how to use yet
Leon
btw what if I wanted Intro to call functions in other Classes too? Would it be Intro extends Navigation extends VideoClass extends Thumbnails?
Leon
Correct, but then you are just chasing Classes and I'd have to look at the entire scope of the Video player before recommending this as the actual solution.
Preston
Yeah, this may be the correct way to do it, but I'm not sure I'm going to go with it after all :/ the static var works fast and with less code
Leon
+2  A: 

Generally it's the responsibility of the container to call functions on its children.

If you want to have (otherwise independent) siblings interacting with each other your container acts as a proxy between the two.

For example, if your application is structured like this:

container
  |
  +-- introInstance
  |
  +-- navigationInstance
  1. container adds a listener for the the CustomEvent.INTRO_CLICKED event on introInstance.

  2. introInstance raises the CustomEvent.INTRO_CLICKED event.

  3. In container's event handler call navigationInstance.introPlayButtonClick().

In this way your Intro class doesn't need to know any thing about your Navigation class and vice-versa, your container forms the glue between the two instances.

Quick note: The container doesn't have to be a literal DisplayObjectContainer with both items on its display list, it just has to have a reference to both instances and know what to do with them.

Sly_cardinal
Ah cool, I'mma try update my code like this
Leon