Realization of the possibility "Step Back" - actionscript-3

I want to implement the ability to step back / forward in the application.
Thought about this: there is some array that references to functions and to step back / forward, you just need to call the last element in the array.
Class Manager:
public class Manager
[...]
private static var _forward:Vector.<Function>;
[...]
public static function set forward(f:Function):void{
_forward.push(f);
}
public static function get forward():Function{
return _forward[_forward.length-1];
}
Use in another class :
[... ]
Manager.forward = _map.moveObject (mo, 0 , 150, -150 );
[... ]
Such use is causing the error .
Is it the correct idea and implementation ? If not, how can I fix this?
Thanks!

It doesn`t work because
_map.moveObject(mo, 0, 150, -150);
returns not function, but the result of the function (in this case, apparently void). To get a reference to a function to do so:
Manager.forward = _map.moveObject;
It is now clear that in addition to the functions and parameters of the need (and their number may vary), and also have to store. Generally this problem is solved with the use of pattern Command. About with this interface:
package
{
public interface ICommand
{
function execute():*;
function undo():void;
function redo();
}
}

Related

How to determine if a Class object represents a class or an interface in actionscript 3.0

I am trying to develop a method in actionscript that takes a Class object as a parameter and will generate an instance of that class at runtime:
public function getComponent(componentType:Class):Object
{
return new componentType();
}
In some cases I may be passed a Class object that represents an interface instead. Naturally I cannot directly create an instance of an interface.
Is there some way to query the Class object and determine whether or not it represents an interface so that I can avoid trying to create an instance in this way?
Assume you follow a naming convention for your interface class, as in the standard IInterfaceName, name of the interface prefixed with a capital "I" following a capital letter and the rest of the class name. There are a couple of ways to do this. If you have a lot of different interfaces that could be passed as a parameter you could do this:
First import the flash.utils.getQualifiedClassName and in your function:
public function getComponent(componentType:Class):Object
{
var name:String = getQualifiedClassName( componentType ).replace(/.*\:+/g,"");
if ( name.search( /^\I[A-Z]/g ) != -1 ) {
trace( "parameter is an interface!" );
return null;
}
return new componentType();
}
You don't have to set the name variable, but this helps make the search a little more strict. You could just do this instead:
if ( getQualifiedClassName( componentType ).search( /\I[A-Z]/g ) != -1 ) {
trace( "parameter is an interface!" );
return null;
}
If you are not already aware, getQualifiedClassName returns the string format of the class name. The regular expressions check specifically for the capital IInterfaceName styled string.
Lastly, if you know it's only one interface, you could simple just do this:
if ( componentType == IMyinterface ) {
trace( "component is a IMyinterface" );
}
After some careful trial and error, I've come up with the following function:
public static function isInterface(clazz:Class):Boolean
{
return describeType(clazz).factory.extendsClass.(#type=="Object").length()==0;
}
Does anyone know if this condition always holds true for all actionscript interfaces?
I think this will work for you:
getQualifiedSuperclassName(classObject);
This will return null if you pass an interface, as interfaces does not have a superclass. It will always give you ANY kind of result for a class, as every class is basically an Object :)
Anyway, I don't think that passing such mixed values to a function is a good idea ;) And checking if the class starts with "I" is worse (sorry Bennett :))
p.s.
Keep in mind that describeType is EXTREMELY slow!

Weird behavior of Red5 service parameters called from Actionscript

I have a Red5 service function that receives a single string as a parameter, and another function that takes no parameters, like the code below:
public class AService
{
private String someName;
public void setName(String aName)
{
someName = aName;
}
.
.
public String makeMessage()
{
return("Hello, "+someName);
}
.
.
other functions
}
I also have an ActionScript function that calls the service function, using the dynamic parameter:
public class Connector
{
private var netConn: NetConnection;
public function invokeCall(theFunc:String,...theParams): void
{
var resp:Responder = new Responder(checkResult);
netConn.call(theFunc,resp,theParams);
}
.
.
}
I am aware that the "...theParams" is actually an array of parameter objects. I also know that the NetConnector class' call() method uses that parameter object array. Unfortunately, when I do an invokeCall() on my service's makeMessage() method (without putting in a parameter) like so:
invokeCall("AService.makeMethod");
I get a function nonexistent message from Red5. The only way I can make it work is to create two invoke methods, one with parameters and one without, and call that function without parameters.
Furthermore, calling my setName() function, like so:
invokeCallwithPrams("AService.setName","factor3");
doesn't seem to work unless I change the signature of my service function:
public class AService
{
private String someName;
public void setName(String[] aName)
{
someName = aName[0];
}
.
.
public String makeMessage()
{
return("Hello, "+someName);
}
.
.
other functions
}
which I don't mind (even though the Red5 documentation indicates that I shouldn't have to treat the parameter as an array), except that when I pass the string "factor3" into the NetConnection class' call() method, somehow it becomes "[factor3]" in setName()!
Obviously, something is screwy here, but I haven't been able to figure it out.
I am using Red5 Version 1.0.1 and my Actionscript is Version 3.
Can anyone explain to me what is going on and (more importantly) how to fix this???
If so, please advise...
UPDATE: The weirdness continues
I did a test in which I changed the parameter of the function I used to set up and invoke the NetConnection class' call() method. Instead of passing it a "...theParams", I changed it to theParams:String, like so:
public function invokeCall(theFunc:String,theParams:String): void
{
var resp:Responder = new Responder(checkResult);
netConn.call(theFunc,resp,theParams);
}
Interestingly, the brackets that appear in my service method setName() go away!
Whatever this problem is, it has something to do with the dynamic parameters in Actionscript. I suspect that I have found a bug in Actionscript 3 that does not allow it to properly handle dynamic parameters that are passed to a method from another method.
Has anyone else seen this problem? Is there any solution? The dynamic parameters are supposed to allow anyone to add parameters as necessary and make them any object that is necessary. Unfortunately, it doesn't look like you can use dynamic parameters passed from another method without them being screwed up.
This looks like a serious bug in Actionscript. Am I correct?
Someone please advise...
I found the solution. It is not a bug in Actionscript, it is a bit of strangeness in the language.
The basic information about the solution can be found here:
AS3 variable length argument expand to call another function with var length args
Based on what is there, I needed to do the following in the method I am using for invokeCallwithParams:
.
.
var conn:Connector = new Connector();
private function invokeCaller(fName:String,...cParams)
{
cParams.unshift(fName);
conn.invokeCall.apply(conn,cParams);
}
This eliminates the unnecessary brackets passed into my setName() service function, meaning that I can pass dynamic, variable length parameters from one method to another...

How can I create a subclass that takes in different parameters for the same function name?

So I have made this simple interface:
package{
public interface GraphADT{
function addNode(newNode:Node):Boolean;
}
}
I have also created a simple class Graph:
package{
public class Graph implements GraphADT{
protected var nodes:LinkedList;
public function Graph(){
nodes = new LinkedList();
}
public function addNode (newNode:Node):Boolean{
return nodes.add(newNode);
}
}
last but not least I have created another simple class AdjacancyListGraph:
package{
public class AdjacancyListGraph extends Graph{
public function AdjacancyListGraph(){
super();
}
override public function addNode(newNode:AwareNode):Boolean{
return nodes.add(newNode);
}
}
Having this setup here is giving me errors, namely:
1144: Interface method addNode in namespace GraphADT is implemented with an incompatible signature in class AdjacancyListGraph.
Upon closer inspection it was apparent that AS3 doesn't like the different parameter types from the different Graph classes newNode:Node from Graph , and newNode:AwareNode from AdjacancyListGraph
However I don't understand why that would be a problem since AwareNode is a subClass of Node.
Is there any way I can make my code work, while keeping the integrity of the code?
Simple answer:
If you don't really, really need your 'addNode()' function to accept only an AwareNode, you can just change the parameter type to Node. Since AwareNode extends Node, you can pass in an AwareNode without problems. You could check for type correctness within the function body :
subclass... {
override public function addNode (node:Node ) : Boolean {
if (node is AwareNode) return nodes.add(node);
return false;
}
}
Longer answer:
I agree with #32bitkid that your are getting an error, because the parameter type defined for addNode() in your interface differs from the type in your subclass.
However, the main problem at hand is that ActionScript generally does not allow function overloading (having more than one method of the same name, but with different parameters or return values), because each function is treated like a generic class member - the same way a variable is. You might call a function like this:
myClass.addNode (node);
but you might also call it like this:
myClass["addNode"](node);
Each member is stored by name - and you can always use that name to access it. Unfortunately, this means that you are only allowed to use each function name once within a class, regardless of how many parameters of which type it takes - nothing comes without a price: You gain flexibility in one regard, you lose some comfort in another.
Hence, you are only allowed to override methods with the exact same signature - it's a way to make you stick to what you decided upon when you wrote the base class. While you could obviously argue that this is a bad idea, and that it makes more sense to use overloading or allow different signatures in subclasses, there are some advantages to the way that AS handles functions, which will eventually help you solve your problem: You can use a type-checking function, or even pass one on as a parameter!
Consider this:
class... {
protected function check (node:Node) : Boolean {
return node is Node;
}
public function addNode (node:Node) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
In this example, you could override check (node:Node):
subclass... {
override protected function check (node:Node) : Boolean {
return node is AwareNode;
}
}
and achieve the exact same effect you desired, without breaking the interface contract - except, in your example, the compiler would throw an error if you passed in the wrong type, while in this one, the mistake would only be visible at runtime (a false return value).
You can also make this even more dynamic:
class... {
public function addNode (node:Node, check : Function ) : Boolean {
if (check(node)) return nodes.add(node);
return false;
}
}
Note that this addNode function accepts a Function as a parameter, and that we call that function instead of a class method:
var f:Function = function (node:Node) : Boolean {
return node is AwareNode;
}
addNode (node, f);
This would allow you to become very flexible with your implementation - you can even do plausibility checks in the anonymous function, such as verifying the node's content. And you wouldn't even have to extend your class, unless you were going to add other functionality than just type correctness.
Having an interface will also allow you to create implementations that don't inherit from the original base class - you can write a whole different class hierarchy, it only has to implement the interface, and all your previous code will remain valid.
I guess the question is really this: What are you trying to accomplish?
As to why you are getting an error, consider this:
public class AnotherNode extends Node { }
and then:
var alGraph:AdjacancyListGraph = new AdjacancyListGraph();
alGraph.addNode(new AnotherNode());
// Wont work. AnotherNode isn't compatable with the signature
// for addNode(node:AwareNode)
// but what about the contract?
var igraphADT:GraphADT = GraphADT(alGraph);
igraphADT.addNode(new AnotherNode()); // WTF?
According to the interface this should be fine. But your implemenation says otherwise, your implemenation says that it will only accept a AwareNode. There is an obvious mismatch. If you are going to have an interface, a contract that your object should follow, then you might as well follow it. Otherwise, whats the point of the interface in the first place.
I submit that architecture messed up somewhere if you are trying to do this. Even if the language were to support it, I would say that its a "Bad Idea™"
There's an easier way, then suggested above, but less safe:
public class Parent {
public function get foo():Function { return this._foo; }
protected var _foo:Function = function(node:Node):void { ... }}
public class Child extends Parent {
public function Child() {
super();
this._foo = function(node:AnotherNode):void { ... }}}
Of course _foo needs not be declared in place, the syntax used is for shortness and demonstration purposes only.
You will loose the ability of the compiler to check types, but the runtime type matching will still apply.
Yet another way to go about it - don't declare methods in the classes they specialize on, rather make them static, then you will not inherit them automatically:
public class Parent {
public static function foo(parent:Parent, node:Node):Function { ... }}
public class Child extends Parent {
public static function foo(parent:Child, node:Node):Function { ... }}
Note that in second case protected fields are accessible inside the static method, so you can achieve certain encapsulation. Besides, if you have a lot of Parent or Child instances, you will save on individual instance memory footprint (as static methods therefore static there exists only one copy of them, but instance methods would be copied for each instance). The disadvantage is that you won't be able to use interfaces (can be actually an improvement... depends on your personal preferences).

Generic way to get reference to a method's caller?

I have 2 classes representing 2 objects. From the "whoCalledMe" function, I want to find out what object called the function (without passing that information in as an argument). I've used a make-believe property, "caller", that would give me the reference I'm looking for. Is there a generic way I can get a reference to the caller from there?
package {
public class ObjectCallingTheFunction {
public var IDENTITY:String = "I'm the calling function!";
public function ObjectCallingTheFunction() {
var objectWithFunction:ObjectWithFunction = new ObjectWithFunction();
objectWithFunction.whoCalledMe();
}
}
}
package {
public class ObjectWithFunction {
public function whoCalledMe ():void {
trace(caller.IDENTITY); // Outputs: "I'm the calling function!"
}
}
}
It would help to know why you need this, because I have a feeling that you don't really. If the method is anonymous, you can bind the 'this' keyword by using .apply on the method:
var foo:Function = function(arg:int):void
{
trace(this);
};
var bar:Object = {
toString: function():String { return "bar"; }
};
var baz:Object = {
toString: function():String { return "baz"; }
};
foo.apply(bar); // <-- Prints "bar"
foo.apply(baz); // <-- Prints "baz"
If the method is an instance method method however, it's a bound method and thus "this" will always point to the instance of the class it's declared in, no matter if you redefine it by using the apply method. If it's a static method, "this" doesn't make sense and the compiler will catch it.
Other than that, there's really no way short of declaring it as a parameter. There used to be a caller property on the arguments object, but it was deprecated when AS3 was released. You can get a reference to the function itself through arguments.callee, but that's not really what you asked for.
In AS3 you can throw an error and then parse the Stack Trace to find out detailed informations.
You can check here for an example:
http://www.actionscript-flash-guru.com/blog/18-parse-file-package-function-name-from-stack-trace-in-actionscript-as3
If you want to find the called function's name you can follow this example:
http://www.flashontherocks.com/2010/03/12/getting-function-name-in-actionscript-3/
I guess you want to know the caller in debug purpose. if so I would recommend setting a breakpoint in the method/function instead of tracing. When the code breaks you can backtrace the caller and a lot more. Works in Flash IDE as well as Flashbuilder. Google "as3 breakpoints" if you are new to breakpoints.
Here is the official Adobe article on using arguments.callee
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/arguments.html
It includes sample code.
Hope this helps.

Referencing getter/setter functions in actionscript 3

How does one get a reference the the getter and setter functions in actionscript 3?
if a method is defined on the calls, e.g.
public function blah():String { ...}
I can get a reference to it by just saying blah or this.blah
How do get a reference to
public function get blah2():String {}
public function set blah2(b:String):void {}
Thanks!
Original response:
Unfortunately, you will not be able to store references to those as functions. The getter and setter methods are actually built around the idea that you shouldn't be able to and they therefore function as a property.
Is there a reason that you need to reference the functions specifically?
The comment I'm responding to:
I want to dynamically add external interface methods based on custom metadata tags, e.g. [External]. I was able to do this for the regular methods, but I'm trying to extend this to getter/setters as well. To do this, I need to get a reference to the function dynamically, so I can execute it with the right args using the apply function.
I think you're better off using a multi-step approach in that case. Since getters and setters function as a property and not a method, it would make sense to test to see if it is a property and then simply assign it a value directly. Would you be able to use this:
if( foo.blah2 is Function )
{
foo.blah2.apply( foo, arr );
}
else
{
foo.blah2 = arr[ 0 ];
}