View Full Version : How do I call a method of the document class from another class?
soggybag
11-13-2007, 12:27 AM
I am creating instances of another class from inside my document class. I want these instances to communicate with the document class, how is this accomplished in AS3?
For example, the document class creates a series of boxes with something like:
var box = new Box();
The document class can now call methods of box with box.method(). The question is how can box call methods within the document class?
Flash Gordon
11-13-2007, 12:31 AM
1) pass an instace of the document class to Box
2) if box is a display object. this.stage.getChildAt(0).method();
ryryguy
11-13-2007, 12:40 AM
"this.stage.getChildAt(0).method();" probably won't compile in strict mode, because getChildAt(0) will return a DisplayObject reference. You need to cast it to your document class first, like so:
var theDoc:MyDocClass = this.stage.getChildAt(0) as MyDocClass;
theDoc.method();
Also, I believe that "root" will work as an alternative to "stage.getChildAt(0)" and may avoid some issues with the "stage" property not being set until the object is added to the display list. You'll still have to cast it to the correct class though.
soggybag
11-13-2007, 12:51 AM
Thanks for the replies.
The idea of passing a reference to the document class to each instance occurred to me. But it seemed a little awkward. I kept thinking there was a better way.
I tried root, but it didn't seem to work. For example I used the following in the the Box Class:
root.method_of_document_class();
Maybe I did not do this correctly?
Flash Gordon
11-13-2007, 01:14 AM
should work just fine.
ryryguy
11-13-2007, 03:19 AM
Again, you'll need to typecast "root" to the document class.
(root as MyDocClass).my_doc_method(); // either
MyDocClass(root).my_doc_method(); // or
soggybag
11-13-2007, 03:29 AM
If you mean:
root.method_of_document_class()
I get the error:
1061: Call to a possibly undefined method delete_me through a reference with static type flash.display:DisplayObject.
soggybag
11-13-2007, 03:33 AM
In the time it took me to type my last reply it seems ryryguy has pointed out what I missing. Thanks for the help.
thatblokemike
01-29-2008, 09:47 PM
you funkin beauty.. thats what i was looking for. cheers ryryguy
Mazoonist
03-09-2008, 04:56 PM
I'm reviving this thread because I've got another (similar) question. The solution offered by ryryguy here works for objects that have been added to the display list. Otherwise, there is no reference to "root."
What I'm wondering is this:
What about a scenario where you have a Document Class that has a public method. Next, let's say the document class creates an object from another class, but it's not added to the display list. Maybe it's not even a display object anyway. Now, the second object ought to be able to call the public method of the Document Class. But how??? If you knew the instance name (or, if you prefer, variable name) of the document class it would be easy. But Flash instantiates the document class for you behind the scenes. If the document class has an instance name or variable name, I've not been able to find it out.
Yes, I know you could declare the method public static instead, and use the name of the Document Class itself to call it, but that's kind of beside the point. Logically, if two objects are both instantiated, one ought to be able to call a public method of the other. But I don't know how to work it if the first object is an object of a document class.
Main.as:
package {
import flash.display.*;
public class Main extends MovieClip {
//this class is the Document Class of the fla
private var another:Another;
public function Main() {
another = new Another();
}
public function getTest() {
trace("get test working");
}
}
}
Another.as:
package {
public class Another {
public function Another() {
//How can this class call the
//public function "getTest()"
//in the "Main" document class?
//What is the instance name of
//the instance of Main????
}
}
}
Anyone know the solution?
soggybag
03-09-2008, 05:29 PM
Lately what I have been doing is creating a public class method that receives a reference to the object you want to communicate with.
public set_main( it ):void {
main = it;
}
Usually I'm using this to communicate with my Main (Document Class).
my_class = new ClassName();
my_class.set_main( this );
This has been working pretty good. But it's not anonymous. It also has a few other issues. You have to set it correctly. I'm not sure how to data type this one, so left that out.
Mazoonist
03-09-2008, 05:39 PM
Hey, thanks, soggybag, that works:
Main.as:
package {
import flash.display.*;
public class Main extends MovieClip {
//this class is the Document Class of the fla
private var another:Another;
public function Main() {
another = new Another(this);
}
public function getTest() {
trace("get test working");
}
}
}
Another.as:
package {
public class Another {
public function Another(main:Main) {
main.getTest();
}
}
}
Pretty cool! I really appreciate it.
Mazoonist
03-09-2008, 06:25 PM
I just found something else that works well: Senocular's "TopLevel" class:
package {
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Stage;
/*
* TopLevel class
* have all document classes extend this
* class instead of Sprite or MovieClip to
* allow global stage and root access through
* TopLevel.stage and TopLevel.root
*/
public class TopLevel extends MovieClip {
public static var stage:Stage;
public static var root:DisplayObject;
public function TopLevel () {
TopLevel.stage = this.stage;
TopLevel.root = this;
}
}
}
With "TopLevel.as" either in the same folder, or somewhere in the classpath, now Main can extend it like so:
package {
import flash.display.*;
public class Main extends TopLevel {
//this class is the Document Class of the fla
private var another:Another;
public function Main() {
another = new Another();
}
public function getTest() {
trace("working");
}
}
}
And now, the instance "another" can call the getTest function in Main like so:
package {
public class Another {
public function Another() {
Main(TopLevel.root).getTest();
}
}
}
Note: I found that the above function call won't work without casting "TopLevel.root" to the datatype "Main."
Edit: Casting it to MovieClip works also. Also, the instance name of the document class still remains a mystery, but I liked your solution of using "this."
There is a good article on working with the display list here: http://developer.yahoo.com/flash/articles/display-list.html
I've found the best method for these types of interactions is events. All of the previous methods rely on a direct connection between the instance and the document class, which inhibits expandability - why would you have a button or something else tell a controlling class what to do?. Much easier is to simply dispatch an event. Then its the document/controller class's job to listen for it and do something about it..
public static const MY_EVENT:String = "MyEvent";
// ...
dispatchEvent(new Event(MY_EVENT));
and the controller listening for it
myClassInstance.addEventListener(MyClassName.MY_EV ENT, listenFunction);
private function listenFunction(event:Event):void {
// What you want the child class to ask the controller to do
}
Mazoonist
03-09-2008, 11:44 PM
Sounds like really good advice, jaga, thank you for that.
Zubaran
04-15-2010, 09:04 AM
I find this works, which may helpful to someone out there? Using a MouseEvent as an example....
//-- in YourDocumentClass.as
package {
// your import statement(s) here
public class YourDocumentClass extends MovieClip {
public function YourDocumentClass() {
// your function statement(s) here
}
function yourCalledFunction(event:MouseEvent):void {
// your function statement(s) here
}
}
}
//-- in YourCallingClass.as
yourMovieClipName.addEventListener(MouseEvent.CLIC K, yourCallingFunction);
function yourCallingFunction(event:MouseEvent):void {
MovieClip(root).yourCalledFunction(null);
}
|
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.