开发者

Can I use apply() with constructor to pass arbitrary number of parameters

I've got a function wich can accept a varible number of parameter with a rest operator.

I want create an object passing the argument collected with the rest operator directly to a constructor without create an object and call an initializing function and without passing the entire array but the parameters ah I do with apply() function.

Is it possible ? Using apply 开发者_如何学Pythondoesn't work.

public function myFunc(...arg) {

     // something link "new MyClass.apply(args)"
     return new MyClass();

}


Unfortunately no. There is no way to make apply work for constructor. What is done generally is to prepare a number of call based on the number of arguments :

public function myFunc(...arg):Myclass {
  switch (arg.length) {
    case 0:return new MyClass();
    case 1:return new MyClass(arg[0]);
    case 2:return new MyClass(arg[0], arg[1]);

    //... etc

    case n:return new MyClass(arg[0], arg[1],..,arg[n]);
    default: throw new Error("too much arguments in myFunc");
  }
}


Well this led me to an interesting long research!

I found this neat SWC file filled with utils for mimicking the AS2 eval(): http://www.riaone.com/products/deval/index.html

And here's a proof of concept that what you're looking for might actually work:

package tests {
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.utils.getQualifiedClassName;
    import r1.deval.D;

    public class RandomTests extends Sprite{

        public function RandomTests() {
            super();

            var test:BitmapData =   create(BitmapData, 100, 100, true, 0x00000000);
            trace(test);
        }


        public function create( pClass:Class, ... pArgs ):* {
            D.importClass(pClass);
            var fullQName:String =  getQualifiedClassName(pClass);
            var qNameSplit:Array =  fullQName.split("::");
            var className:String =  qNameSplit[1];
            fullQName =             qNameSplit.join(".");

            var statements:String =
            "import $0;\n" +
            "return new $1($2);";


            var args:Array =        [];
            for (var a:int = 0, aLen:int = pArgs.length; a < aLen; a++) {
                switch(pArgs[a].constructor) {
                    case String:
                        args[a] =   "\"" + pArgs[a] + "\"";
                        break;
                    default:
                        args[a] =   pArgs[a];
                        break;
                        //throw new Error("Unhandled type, please add it: " + pArgs[a].constructor);
                }
            }

            return D.eval(XString.gsub(statements,[fullQName, className, args.join(",")]));
        }
    }

}

Sorry for the bits of dependencies (Like my XString class for easy sub-replacements) but it does work in theory. The only issue would be passing object references as argument entries. But then again... the r1.deval.D class might be able to take it... hmm.

Anyways, thought maybe this would be worth sharing.


well there's also this

public function myFunc(args:Object) {

   //then access various argumens
   return new MyClass(args.name, args.id, args.active)

}

and call it through myFunc({id:33,name:'jo')

you could then pass the object, or is this too far from what you're looking for?


I'm searching for the answer too, but too sad to see the answer is no....

Here's my current (not so good) way to do this kind of stuff, hope some of you interest:

// Foo.as
public class Foo {
    // construct
    public function Foo(... args):void {
        create.apply(this, args);
    }

    // this function do as a really construct function, tricky stuff
    function create(id:uint, name:String) {
        trace(id, name);
    }
}

// Bar.as
// for create this kind of class, just new it as usual
...
var foo:Foo = new Foo(123, "abc");
...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜