Могу ли я использовать apply () с конструктором для передачи произвольного количества параметров - PullRequest
6 голосов
/ 06 октября 2010

У меня есть функция, которая может принимать переменное число параметров с помощью оператора rest.

Я хочу создать объект, передав аргумент, собранный с помощью оператора rest, непосредственно в конструктор, не создавая объект и не вызывая инициализирующую функцию и не передавая весь массив, но параметры я делаю с функцией apply ().

Возможно ли это? Использование apply не работает.

public function myFunc(...arg) {

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

}

Ответы [ 4 ]

14 голосов
/ 06 октября 2010

К сожалению нет. Нет способа заставить применить работу для конструктора. Как правило, выполняется подготовка номера вызова на основе количества аргументов:

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");
  }
}
2 голосов
/ 14 октября 2010

Ну, это привело меня к интересному длинному исследованию!

Я обнаружил, что этот аккуратный SWC-файл заполнен утилитами для имитации AS2 eval (): http://www.riaone.com/products/deval/index.html

И вот подтверждение концепции, что то, что вы ищете, может действительно работать:

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(",")]));
        }
    }

}

Извините за биты зависимостей (как и мой класс XString для простых подстановок), но теоретически он работает. Единственной проблемой будет передача ссылок на объекты в качестве аргументов. Но опять же ... класс r1.deval.D мог бы принять это ... хм.

Во всяком случае, подумал, может быть, это стоит поделиться.

0 голосов
/ 03 ноября 2011

Я тоже ищу ответ, но слишком грустно видеть, что ответ - нет ....

Вот мой нынешний (не очень хороший) способ делать подобные вещи, надеюсь, некоторые из вас заинтересуются:

// 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 голосов
/ 06 октября 2010

ну, есть еще это

public function myFunc(args:Object) {

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

}

и назовите его через myFunc({id:33,name:'jo')

, тогда вы могли бы передать объект, или это слишком далеко от того, что вы ищете?1007 *

...