I want a function to be able to take in various types. AS3 doesn't support overloading directly... so I can't do the following:
//THIS ISN'T SUPPORTED BY AS3
function someFunction(xx:int, yy:int, someBoolean:Boolean = true){
//blah blah blah
}
function someFunction(arr:Array, someBoolean:Boolean = true){
someFunction(arr[0], arr[1], someBoolean);
}
How can I work around it and still have a function that is able to take arguments of various types?
If you just want to be able to accept any type, you can use * to allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ... (rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}
Could just have:
function something(...args):void
{
trace(args[0], args[1]);
}
This way you can easily loop through your arguments and such too (and even check the argument type):
function something(...args):void
{
for each(var i:Object in args)
{
trace(typeof(i) + ": " + i);
}
}
something("hello", 4, new Sprite()); // string: hello
// number: 4
// object: [object Sprite]
Related
I have a function that looks like this:
abc = function (func) {
let object = {};
return function() {
let arg = ???
if (*something*) {
object[arg] = func.apply(this, arg);
}
else {
return object[arg];
}
}
};
My problem is, how do I refer to arg if arg is an extra argument passed to abc?
Thank you!
Its usual to use Mouse Event Listener like this :
MyButton.addEventListener(MouseEvent.MOUSE_UP, MyFunction);
function MyFunction(event:MouseEvent):void
{
// my function codes
//...
//...
}
but I want use a variable in my function , something like this:
//var Tx:Number = any Formula;
MyButton.addEventListener(MouseEvent.MOUSE_UP, MyFunction(Tx));
function MyFunction(event:MouseEvent,T:Number):void
{
if ( T == 1 ) { ... }
if ( T == 2 ) { ... }
if ( T == 3 ) { ... }
}
How can I do it ?
i'd imagine you will attach the listener to different button/movieclips. then, access the event.currentTarget and change the value of your variable.
button1.addEventListener(MouseEvent.MOUSE_UP, doSomething);
button2.addEventListener(MouseEvent.MOUSE_UP, doSomething);
function doSomething(event:MouseEvent):void {
var str:String;
if (event.currentTarget.name == 'button1')
str = 'one';
else
str = 'two';
}
or something like that.
It seems to me you want to create a closure
function process(t:Number)
{
return function(event:MouseEvent) {
if ( t == 1 ) { ... }
if ( t == 2 ) { ... }
if ( t == 3 ) { ... }
}
}
MyButton.addEventListener(MouseEvent.MOUSE_UP, process(1));
This will return a function from "process" that will act a the event listener and that encloses the parameter T.
ps: Even thou ActionScript allows hoisted functions (that is functions that are called before they are defined) I would regard that as bad style. Also use lowercases as Parameter names. Uppercase names are usually a hint that this is a Type.
I am new to ActionScripting but I have done some Java. I was told they are kinda similar. I am coding my swf file with some AS3 integrated.
function init():void{
// do something
}
function init(var string:String):String{
// do something else
}
is this not allowed in AS? If not, is there another way of handling it besides?
Thanks in advance.
Yes, you can override functions. But the example you gave is not overriding - it's overloading. For overriding a function, you basically just create a function with the same signature and everything in a subclass and add the word "override" right before it.
You can't directly overload a function though. If you want a variable number of parameters, you have to use optional parameters instead. Like this:
function init(str:String = null):String
{
if (str == null)
{
// do one thing
return null;
}
else
{
// do another thing
return "someString";
}
}
And that's about the best you're going to be able to do in AS3. The inability to overload functions, at least strictly speaking, is a fairly common complaint and obvious shortcoming of the language.
Do you mean method overloading? Actionscript, sadly, does not support this.
To get around it, you can use default parameters, or just make your parameters a bit less constraining. This answer has some details on that.
You could try this:
function init(var string:String = "Default value"):String{
// do something
}
Actionscript does not support method overloading. However, based on the answer to this question you have other options.
If you just want to be able to accept any type, you can use * to
allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is
unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ...
(rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of
classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}
This AS3 function works for normal methods and getter methods:
public function MyClassTestAPI(functionName:String, ...rest):* {
var value:*;
try {
switch(rest.length) {
case 0:
value = myObj[functionName];
break;
case 1:
value = myObj[functionName].call(functionName, rest[0]);
break;
case 2:
value = myObj[functionName].call(functionName, rest[0],rest[1]);
break;
default:
throw("Cannot pass more than 2 parameters (passed " + rest.length + ")");
}
}
return value;
}
Sample usage:
this.MyClassTestAPI("Foo", "arg1"); // tests function Foo(arg1:String):String
this.MyClassTestAPI("MyProperty"); // tests function get MyProperty():String
this.MyClassTestAPI("MyProperty", "new value");// tests function set MyProperty(val:String):void
The third call does not work (throws exception).
How can I make it work for setter methods as well?
Thanks!
edit:
This is a version that works, except with getter and setter that have additional parameters.
It is ok for my needs:
public function MyClassTestAPI(functionName:String, ...rest):* {
var value:*;
try {
if (typeof(this.mediaPlayer[functionName]) == 'function') {
switch(rest.length) {
case 0:
value = myObj[functionName].call(functionName);
break;
case 1:
value = myObj[functionName].call(functionName, rest[0]);
break;
case 2:
value = myObj[functionName].call(functionName, rest[0],rest[1]);
break;
default:
throw("Cannot pass more than 2 parameters (passed " + rest.length + ")");
}
} else {
switch(rest.length) {
case 0:
value = myObj[functionName];
break;
case 1:
myObj[functionName] = rest[0];
break;
default:
throw("Cannot pass parameter to getter or more than one parameter to setter (passed " + rest.length + ")");
}
}
}
return value;
}
Setter functions works as variables, so you can't use it in this way:
myProperty.call( "new value" );
Your function for variables is pointless, because you just have to do a value assignment:
myProperty = "new value";
By the way you can include it in your function in two ways:
create a third parameter what tells your function it is a function or variable
create the value assignment in the catch section
You are currently passing only one string with value "new value"
This should do the trick:
this.MyClassTestAPI("MyProperty", "new","value");
For more information on this matter check the Adobe LiveDocs at:
http://livedocs.adobe.com/flex/3/html/help.html?content=03_Language_and_Syntax_19.html
Cheers
Why do you think the code below does not work?
What would you change/add to make it work?
Any help is appreciated..
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function, ...args):void
{
bb(f, args);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:Array = null;
function bb(f:Function, ...args):void
{
func = f;
argum = args;
exec();
}
function exec()
{
func.apply(null, argum);
}
I get an ArgumentError (Error #1063):
Argument count mismatch on test_fla::MainTimeline/TraceIt(). Expected 2, got 1.
..so, the passed parameter (argum) fails to provide all passed arguments..
..Please keep the function structure (traffic) intact.. I need a solution using the same functions in the same order.. I have to pass the args to a variable and use them in the exec() method above..
regards
Ok, here is the solution.. after breaking my head : )
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function=null, ...args):void
{
var newArgs:Array = args as Array;
newArgs.unshift(f);
bb.apply(null, newArgs);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:*;
function bb(f:Function=null, ...args):void
{
func = f;
argum = args as Array;
exec();
}
function exec():void
{
if (func == null) { return; }
func.apply(this, argum);
}
This way, you can pass arguments as variables to a different function and execute them..
Thanks to everyone taking the time to help...
When TraceIt() eventually gets called, it's being called with 1 Array parameter, not a String and int parameters.
You could change TraceIt() to:
function TraceIt(args:Array)
{
trace(args[0], args[1]);
}
Or you could change exec() to:
function exec()
{
func.apply(null, argum[0].toString().split(","));
}
...as it appears when you pass "test", 1, you end up with array whose first value is "test,1". This solution doesn't work beyond the trivial case, though.
Change your bb function to look like this:
function bb(f:Function, args:Array):void
{
func = f;
argum = args;
exec();
}
As you have it now, it accepts a variable number of arguments, but you are passing in an array(of the arguments) from aa.