AS3: Using Instance Variables as Default Parameter Values - actionscript-3

I am trying to use an instance variable as a parameter value in a method, but it is giving me an error. "Parameter initializer is unknown or is not a compile-time constant"
I want to use a non-constant instance variable though, and I assume there has to be some way around this besides calling this method from another method. Here is the code I'm referring to:
public function attack(target:Fighter=this.target):void {
}

What about:
public function attack(target:Fighter):void
{
if(target == null)
target = this.target;
}
and to be honest maybe it's easier to name one of variables _target to avoid confusion. You can use target = _target; instead of this..

You cannot set an optional parameter that way. You can set optional parameters to a default value but not a reference. In this case if you want to keep it optional you could do something like this (or what #George Profenza suggested):
public function attack(target:Fighter=null):void {
target = target ? target : this.target;
}
I see that you marked a correct answer already, but I'll explain that since you are defaulting any null parameters to this.target you would benefit from using this solution so you don't have to pass null each time you call attack() i.e. - you can do attack() instead of attack(null).

Related

Which is better for returning result of some method or instance of a class? and why?

I was just wondered which is better way for returning some result of function or instance of Class?
1)
FN() {
var result = callSomeFN();
return result;
}
InitClass(int typeId): MyClass {
MyClass class = new MyClass(typeId);
return class;
}
2)
FN() {
return callSomeFN();
}
InitClass(int typeId): MyClass {
return new MyClass(typeId);
}
The only difference I see here is the declaration of a variable. I wouldn't say one is better than the other. If the variable is never going to be used why bother defining it? Just return.
I suppose if you really wanted to nitpick it would depend on if you're returning a value or reference type. If it's a reference it doesn't matter since you're going to store something in memory and return a pointer (both the variable and the return value are just pointers to the same memory space). If it's a value type it will end up copying the value and disposing of the version within the function scope. If the variable is never used why create something just to destroy it? The default behavior would be highly language dependent, which you didn't specify.

AS3: Not getting typeError when calling a function

I'm writing my own language from ActionScript as a personal project (yeah, I guess AS3 is not the best language to build a language from, but never mind that).
NOTE: I have checked several times, and my compiler's option 'Enable Strict Mode' is set to True. I have tried setting it to False to try, but I didnt get a different result.
At any rate, I have a this:
package NodyCode.Classes
{
public class NCString
{
var value:String;
public function NCString(expression:String = "") {
value = expression;
}
public function rindex(substr:NCString, startIndex:int = 0x7fffffff):uint {
//code here
}
}
}
Since I'm writing my own language, I need to make sure functions and methods can take un unlimited number of arguments. For this reason, I'm using an anonymous function so that I can use the apply method. Like so:
//This code is in a class named ClassMethods
public static var StringMethods:Object = {
rindex: function(substr:NCString, startIndex:int = 0x7fffffff):uint {
return this.rindex(substr, startIndex);
}
}
And, somewhere else in my code, I do the call:
return ClassMethods.StringMethods["rindex"].apply(ncstr1, [ncstr2, [5]]);
I would like an error to be thrown whenever the user uses the wrong type of argument.
So, in this case, I call the rindex method on ncstr1, with arguments: substr = ncstr2 and startIndex = [5]. Notice that, according to my anonymous function's definition, startIndex is supposed to be an int, not an Array.
So, I expected an error to be thrown. Instead, though, rindex is called with startIndex = 5.
Why is [5] converted to 5, and is there any way for me to prevent that? If there isn't, I can always work around this problem, but I'd rather not if I can do otherwise.
EDIT: Finally understood that I did not mention I was using an anonymous function.
Are you compiling with strict mode set to false? (See here also.)
The strict option: "Prints undefined property and function calls; also performs compile-time type checking on assignments and options supplied to method calls".
It defaults to true, but if it got set to false somehow, compile-time checks might be disabled. I'd check your compiler settings (whether in an IDE or if you're compiling on the command-line) and make sure they're correct.
Okay, so here's what was said in the comments:
I did have my compiler on strict mode. The reason for which I was not getting an error is because I was using the apply method of an anonymous function. The type checks are loosened when using the apply method. That's why [5] was coerced to 5.
There is apparently no way to prevent this.

AS3: Is it possible to give a vector function argument a default value?

I have a function where I'd like to make a vector argument optional-- that is, something like this:
public function test(arg1:int, arg2:Vector.<int> = new Vector.<int>(5)) {}
So in that example, I want the first argument to be required, and an optional vector passed in. If the second argument is not provided, create an int vector with 5 elements instead. It throws a compile error: "Parameter initializer unknown or is not a compile-time constant."
Making the argument not optional works, as in:
public function test(arg1:int, arg2:Vector.<int>) {}
But that's not exactly what I'm looking for. Doing some searching I found a supposed workaround, which is
public function test(arg1:int, arg2:Vector.<int> = null) {}
But that doesn't compile either.
I've already moved on in my code with a workaround just to be done with it, but I'm still curious. Can you have a vector as a default argument, and how?
I don't think this is possible. Probably just because the compiler was never programmed to handle this situation because optional parameters do work with many other datatypes in AS3. I did some research and other have reported the same issue as you with no success in setting an empty vector object in the function declaration.
I would simply do the following if you haven't already:
var myDefaultVector:Vector.<int> = new Vector.<int>(5);
function test(arg1:int, arg2:Vector.<int> = null) {
if( arg2 == null ) {
arg2 = myDefaultVector;
}
// rest of your code
}
I have tried compiling the above code in Flash and it compiled successfully.

Function.call(someInstance,args) for methodes. Ignores first arg

In as3 there is a flexible way to change object instance, when calling it.
call or apply members of Function object can be called with specific first arg, and reference say us, that this first arg will be "this" pointer inside function. But i've found it wrong.
I'v write little test, listed below.
public class Test
{
private var name:String = "default";
public var test3:Function = test;
public var test2:Function = function()
{
trace(this.name);
}
public function Test(name:String)
{
this.name = name;
}
public function test():void
{
trace(this.name);
}
}
and tested it.
var tmp:Test = new Test("default");
tmp.test(); //out default
tmp.test.call(new Test("new")); //out default
tmp.test2(); //out default
tmp.test2.call(new Test("new2")); //out new2
tmp.test3(); //out default
tmp.test3.call(new Test("new3")); //out default
So, in anonymous function call we can get right output, but not in case of member function.
maybe it's becouse of ambiguous "this" pointer, that should reffer real object instance for correct work, maybe smth else. I dont now, and as3 reference didnt't describe smth about it.
Finally list of questions:
Why so? By me, it's very strange, and looks like undefined behaviour;
How i can achieve that functionality? How to deceive test function like anonymous one? Isn't it call methode target?
It isn't very important, but I'll be glad any good answer. Thanks!
P.S. sorry for my English.
//EDITED: added this statement to all "name" references. Nothing changes.
When invoking the [[Call]] property, the behavior is different for
different types of closures. A closure is an object that contains a
reference to a method, and the [[Call]] property acts differently
depending on whether it is a function, method, or class closure. A
function closure is one that is of a global method that isn't
associated with any instance of a class. A method closure contains an
instance method of a class, and will always remember its original
"this" value.
If the closure is a function closure, then the first argument passed
to [[Call]] is passed on to the method and gets used as the "this"
value. If the first argument is null or undefined, then the global
object will be used as the "this" value for the method.
If the closure is a method closure, then the first argument of
[[Call]] will be ignored, and the saved "this" value for the method
closure will be passed to the method as the first argument. A method
closure records what its original "this" value was and always uses
that instead of the first argument to [[Call]].
If the closure is a class closure, and there is 1 argument passed to
[[Call]] (in addition to the "this" argument), then the call is
treated as a type conversion, and the argument will be coerced to the
type represented by the closure.
http://learn.adobe.com/wiki/display/AVM2/2.4+Method+invocation+notes

TypedFactoryFacility: Passing null argument

Consider the following test:
[Test]
public void Create_ServiceWithDynamicDependency_Created()
{
// arrange
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IServiceFactory>().AsFactory());
container.Register(Component.For<ServiceWithDynamicDependency>().LifeStyle.Transient);
container.Register(Component.For<SomethingStatic>().LifeStyle.Transient);
var factory = container.Resolve<IServiceFactory>();
// act
ServiceWithDynamicDependency serviceWithDynamicDependency = factory.Create(null);
// assert
Assert.That(serviceWithDynamicDependency, Is.Not.Null);
}
This fails with the following exception: Could not resolve non-optional dependency for 'Testing.Windsor.Factory.ServiceWithDynamicDependency' (Testing.Windsor.Factory.ServiceWithDynamicDependency). Parameter 'somethingDynamic' type 'System.String'
If I replace the assert part with this:
ServiceWithDynamicDependency serviceWithDynamicDependency = factory.Create("foo");
The component is resolved as expected. Does anyone know of a workaround for this or do I have to hand-roll factories which accepts null arguments?
Although you didn't specify it I'm assuming your component has one constructor that looks like this:
public ServiceWithDynamicDependency(string somethingDynamic) {}
The behavior you're observing is not a bug - this is by design, and here's why.
If a value is required an actual value has to be provided, and null is not considered to be a correct value. Otherwise Windsor would just be passing null in for every constructor instead of bothering to find actual dependencies for that.
null is a special value in .NET and it means "no value". So even though you explicitly provide null as an argument Windsor will ignore it.
To solve this, instead of working around be explicit that the value is optional and provide a second constructor that does not include it.
Windsor is smart enough to pick the right constructor and if the value is not provided (or null as in your case) it will pick the no-argument constructor, and when the value is there (is not null) it will pick the one with the value.