Calling functions in Actionscript: "Term is undefined and has no properties" - actionscript-3

I'm writing a genetic fitness program, and I'm currently writing some code that will calculate the 'fitness' value of each organism.
I'm trying to call a function that initializes each genotype;
function random_genotype_initialisation():void
{
//stuff
}
By using the typical method-calling I'm used to in C# and Java;
random_genotyoe_initialisation();
However this returns the error: "TypeError: Error #1010: A term is undefined and has no properties."
I've looked elsewhere for help, and I've found suggestions such as declaring a variable and 'calling' that.
var rep = replicate_new_generation();
rep.call();
Any suggestions?

I assume there's an undefined value inside your random_genotype_initialisation() function. You are correct, you call a function in as3 same as in java/c/c++/c#/js/etc.
The snippet is a bit wrong because you store the result of the replcate_new_generation into rep, but that is a void function, so rep will be void and therefore not have call():
var rep = replicate_new_generation();//rep = void at this point
rep.call();//call does not exist for rep
Do you mean ?
var rep:Function = replicate_new_generation;
rep.call();
Which is same as: replicate_new_generation();
If the error is generating within the function perhaps you should post the body
of the function as well ?

C# is VERY similar to AS3, I have no idea what you are trying to do or why your code did not work since you didn't provide a very good example. But you can call functions directly as long as it is accessible just in any normal way.
say, inside a class you have:
class Boo {
private function foo():void {
trace("bar");
}
public function foobar():void {
foo();
}
}
class FoobarCaller {
public function FoobarCaller (){
var asdf:Boo = new Boo();
asdf.foobar();
}
}
that works, just as it would in C# or any other "standard coding language. However, without a better question it's impossible to say what it is you have done wrong

Related

Can I still create Global variables in AS3

Following the answer here, I have created a file called MyGlobals.as and placed some global variables and functions so that I can access it from anywhere within my project just like AS3 buil-in functions such as trace() method.
This is MyGlobals.as which is located in the src folder (top level folder)
package {
public var MessageQueue:Array = new Array();
public var main:Main;
public var BOOKING_STATUS_DATA:Object;
public function postMessage(msg:Object):void {
MessageQueue.push(msg);
}
public function processMessage():void {
var msg:Object = MessageQueue.pop();
if (msg) {
switch (msg.type) {
}
}
}
Looks like my IDE (FD4) is also recognizing all these functions and variables and also highlighting the varibles and functions just like any other built-in global functions. However, I am getting compilation errors "Accessing possibly undefined variable xxx". The code is as simple as trace(MessageQueue) inside my Main (or another classe).
I am wondering if there was any change Adboe has done recently that it can't be done now or am I missing something? I am not sure if I need to give any special instructions to FD to include this MyGlobals.as?
I am using FD4, Flex SKD 3.1, FP12.0
I am aware of the best practices which suggests to avoid using this type of method for creating global variables but I really need it for my project for my comfort which I feel best way (right now) when compared to take any other path which involves daunting task of code refactoring. I just want do something which can be done in AS3 which I guess is not a hack.
I've done some playing around; it looks like you can only define one (1) property or method at package level per .as file. It must be the same name (case-sensitive) as the .as file it is contained in.
So no, nothing has changed since the older Flash Versions.
In your case that would mean you need five separate ActionScript files along the lines of:
MessageQueue.as:
package
{
public var MessageQueue:Array;
}
main.as:
package
{
public var main:Main;
}
...etc. As you can see this is very cumbersome, another downside to the many others when using this approach. I suggest using the singleton pattern in this scenario instead.
package{
public class Singleton{
private static var _instance:Singleton=null;
private var _score:Number=0;
public function Singleton(e:SingletonEnforcer){
trace(‘new instance of singleton created’);
}
public static function getInstance():Singleton{
if(_instance==null){
_instance=new Singleton(new SingletonEnforcer());
}
return _instance;
}
public function get score():Number{
return _score;
}
public function set score(newScore:Number):void{
_score=newScore;
}
}
}
then iin your any as3 class if you import the singleton class
import Singleton
thn where u need to update the global var_score
use for example
var s:Singleton=Singleton.getInstance();
s.score=50;
trace(s.score);
same thing to display the 50 from another class
var wawa:Singleton=Singleton.getInstance();
trace(wawa.score)

What are _loc_ variables when swfs are decompiled into AS3?

When running swfs through decompilers (my own swfs, not somebody else's), I've noticed a lot of mention of certain variables:
_loc_1
_loc_2
_loc_3
.
.
.
_loc_n
As in the following example:
private function templateFilterFunction(param1) : Boolean
{
var _loc_2:* = false;
if (filterFunction != null)
{
_loc_2 = filterFunction(param1, typedText);
}
return _loc_2;
}
Alright, so these are apparently just normal variables then, right? And they may have had more descriptive names in the original AS3 code, but that's been lost in the bytecode, and now we have the same variables as before, just with non-descript names, right?
Not exactly. For instance:
package
{
public class SomeClass extends Object
{
public var var1:Number;
public var var2:Number;
public var var3:Number;
public function SomeClass(param1:Number, param2:Number, param3:Number)
{
if (!_loc_5)
{
if (!_loc_4)
{
var3 = param1;
if (!_loc_4)
{
var1 = param2;
}
}
}
var2 = param3;
return;
}// end function
}
}
These aren't declared. But they're not exactly members of Object either, and I've never seen them outside of a swf decompilation. What are they then? Thanks.
Not sure about that particular piece of code, but the decompilers I've used (as far as I remember) all call the local variables loc_n, local_n or something like that.
I think you already know why. Local variables are created and pushed onto the execution stack; they are not referenced from outside the local scope and since they are not callable by name, their names are just whipped off the bytecode. (The object pointed by the variable could be allocated on the heap and live outside the scope of the function, however, but that's not the point here).
Now, another thing you might be aware of is that some bytecode generated by the compiler just doesn't traslate to actionscript code. There are things that can be done in bytecode that are not really possible in AS code; an example, off the top of my head: the "dup" opcode (duplicates a value and pushes it onto the stack). There are others (jumps, noops, etc). Reversing this to the original source code is sometimes not possible.
There are other interesting cases such as loops. You may notice that a particular decompiler tends to generate "for loops" (or "while loops") regardless of whether the source code had a for or a while. That's because loops are a higher level construct that are usually implemented in bytcode as conditional jumps. If you want to reverse the bytecode to AS code, you just have to pick a flavor because the loop (as an AS construct) is just not there.
That said, I've seen some decompilers (can't remember which one now) generating invalid or non-sensical source code. To me, that's the case in the example you post. I may be wrong but it seems like the _loc_5 and _loc_4 vars are just gibberish and the original code must be something like:
public function SomeClass(param1:Number, param2:Number, param3:Number):void
{
var var3:Number = param1;
var var1:Number = param2;
var var2:Number = param3;
}

What is wrong with this as3 piece of code?

I'm an as3 newbie and I'm trying to send a message through netstream to a function that will handle it.
Here is the line that sends
public function _attachLocalVideoAndAudio(muteCam:Boolean = false, muteMic:Boolean =
false):void
{
...
_outgoingStream.send("flagVideo",true);
...
}
public function flagV():Boolean
{
var client:Object;
client.flagVideo=function(flag:Boolean):void{
check=flag;
}
return check;
}
*check is defined
I'm using Monster Debugger to debug and it seems that there is a problem with the inner function that handles the flag. There isn't much tutorials on the web on netstream.send() but I wrote this code based on something I saw online.

Value Will Set properly, but Get receives Null

So, I have successfully grabbed a value out of an XML document and set it into a separate class called "AddCommas." The trace functions have shown me that it sets properly.
For more details, my objective is to take the language indicator ("fr" for french or "en" for english), set it inside the appropriate class and into a variable I will use. Now, I am using this variable to be used in an if statement; which will help me format a number properly (commas, decimals, spaces) per the clients request.
However, my problem is when I try to get the value to use it. It always comes back as Null. I have placed traces all over my program trying to pinpoint when this happens, but I cannot find it. Here's the code...
The pull from the XML file and into the set (this works fine, but I am adding it for your benefit in case I missed something)
public var commaHold = new AddCommas();
localLanguage = xmlObj.localLanguage;
trace("localLanguage + " + localLanguage);
commaHold.setLanguage(localLanguage); // Set Language
//More code follows...
This is the set function istelf...
public function setLanguage(localLanguage:String){
langHold = localLanguage;
trace("Set Language = " + langHold); //This always shows a successful set
}
Now am I wrong in thinking that in AS3, once langHold in my AddCommas class has been set I should be able to use it without calling a get within the function I am using the If Statement in, right? Such as this?
var language = langHold;
if (language == "en"){
trace("Language is = " + language); // More code follows afterwards and as of now, this shows NULL
Now, I have attempted plenty of Get functions to add the language variable in the call itself to this function and it's always the same. Am I missing some fundamentals here?
Thank you very much for your time.
If you expect a string comparison you need to use quotes, unless en is a String variable since langHold is a String, like:
if (language == "en"){
Consider modifying the set function to use the as3 keyword like:
private var _language:String;
public function set language(value:String):void {
_language = value;
//do other stuff here if necessary, put a breakpoint on the line above
}
public function get language():String{
return _language;
//put a breakpoint on the line above
}
You should be able to see when any instance of your class has the property changed. The only other issue I can think of is it is not the same instance of the class and therefore doesn't share the property value you set earlier. In the debugger you can check the "hashCode" or "address" it shows for this to see if it changes when it hits the breakpoints.
Here's a sample Singleton structure in AS3 (this all goes in one file):
package com.shaunhusain.singletonExample
{
public class SingletonExample
{
private static var instance:SingletonExample;
public static function getIntance():SingletonExample
{
if( instance == null ) instance = new SingletonExample( new SingletonEnforcer() );
return instance;
}
/**
*
* #param se Blocks creation of new managers instead use static method getInstance
*/
public function SingletonExample(se:SingletonEnforcer)
{
}
}
}
internal class SingletonEnforcer {public function SingletonEnforcer(){}}
using this single shared instance from any other class would look something like this:
private var singletonInstance:SingletonExample = SingletonExample.getInstance();
ShaunHusain's theory of using a Singleton was the perfect solution I needed. However, his code gave me a bizarre 1061 error and my format and code appeared to be error free. Regardless, I looked up another way to use a Singleton as follows that worked perfectly for me. Honestly, Shaun's code should work for anyone and I have no idea why it wasn't. I am perfectly willing to admit that it was probably a typo on my end that I just did not see.
I ended up embedding the Set and Get within the Singletons class and used it as an intermediary to hold the information I needed. It worked perfectly.
package chart {
import chart.*;
//
public class StaticInstance {
private static var instance:StaticInstance;
private static var allowInstantiation:Boolean;
private var language:String;
public static function getInstance():StaticInstance {
if (instance == null) {
allowInstantiation = true;
instance = new StaticInstance();
allowInstantiation = false;
}
return instance;
}
public function StaticInstance():void {
if (!allowInstantiation) {
throw new Error("Error: Instantiation failed: Use StaticInsance.getInstance() instead of new.");
}
}
public function setLanguage(_language:String):void{
language = _language;
trace("language set = " + language);
}
public function getLanguage():String{
return language;
}
}
}
This code allowed me to hold the data and call upon it again from two different classes. It's a very hack job instead of just being able to pass on the variable from function to function, but in my case we didn't create this file, we are modifying it and attempting to do things beyond the original scope of the project.
Thanks again for your help Shaun! I hope this helps other people!

Can a Flex 3 method detect the calling object?

If I have a method such as:
private function testMethod(param:string):void
{
// Get the object that called this function
}
Inside the testMethod, can I work out what object called us? e.g.
class A
{
doSomething()
{
var b:B = new B();
b.fooBar();
}
}
class B
{
fooBar()
{
// Can I tell that the calling object is type of class A?
}
}
Sorry the answer is no (see edit below). Functions received a special property called arguments and in AS2 it used to have the property caller that would do roughly what you want. Although the arguments object is still available in AS3 the caller property was removed from AS3 (and therefore Flex 3) so there is no direct way you can do what you want. It is also recommeded that you use the [...rest parameter](http://livedocs.adobe.com/flex/3/langref/statements.html#..._(rest)_parameter) language feature instead of arguments.
Here is a reference on the matter (search for callee to find the relevant details).
Edit: Further investigation has shown that it is possible to get a stack trace for the current executing function so if you are lucky you can do something with that. See this blog entry and this forum post for more details.
The basic idea from the blog post is you throw an Error and then catch it immediately and then parse the stack trace. Ugly, but it may work for you.
code from the blog post:
var stackTrace:String;
try { throw new Error(); }
catch (e:Error) { stackTrace = e.getStackTrace(); }
var lines:Array = stackTrace.split("\n");
var isDebug:Boolean = (lines[1] as String).indexOf('[') != -1;
var path:String;
var line:int = -1;
if(isDebug)
{
var regex:RegExp = /at\x20(.+?)\[(.+?)\]/i;
var matches:Array = regex.exec(lines[2]);
path = matches[1];
//file:line = matches[2]
//windows == 2 because of drive:\
line = matches[2].split(':')[2];
}
else
{
path = (lines[2] as String).substring(4);
}
trace(path + (line != -1 ? '[' + line.toString() + ']' : ''));
Is important to know that stackTrace is only available on the debugger version of Flash Player. Sorry! :(
I'd second the idea of explicitly passing a "callingObject" parameter. Unless you're doing really tricky stuff, it should be better for the caller to be able to supply the target object, anyway. (Sorry if this seems obvious, I can't tell what you're trying to accomplish.)
To add to the somewhat ambiguous first paragraph of James: the arguments property is still available inside a Function object, but the caller property has been removed.
Here's a link to the docs: http://livedocs.adobe.com/flex/3/langref/arguments.html
This might help someone, I'm not sure... but if one is using an Event this is possible using the e.currentTarget as follows:
private function button_hover(e:Event):void
{
e.currentTarget.label="Hovering";
}