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

馋奶兔 提交于 2019-11-28 11:26:37

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");
...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!