【问题标题】:Can I use apply() with constructor to pass arbitrary number of parameters我可以使用 apply() 和构造函数来传递任意数量的参数吗
【发布时间】:2011-04-21 22:50:40
【问题描述】:

我有一个函数,它可以接受带有休息运算符的可变数量的参数。

我想创建一个对象,将使用 rest 运算符收集的参数直接传递给构造函数,而不创建对象并调用初始化函数,并且不传递整个数组,但参数啊,我使用 apply() 函数。

有可能吗?使用 apply 不起作用。

public function myFunc(...arg) {

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

}

【问题讨论】:

  • 我很遗憾看到这无法完成,因为我正在扩展 Array 以创建一个 ConstantArray,一旦通过构造函数创建它,就删除了所有添加和删除它的能力。我猜我仍然可以在每个循环中执行 super.push(),:( 不如 super.apply(this, rest)

标签: flash actionscript-3 constructor new-operator apply


【解决方案1】:

很遗憾,没有。没有办法使构造函数的应用工作。通常所做的是根据参数的数量准备一些调用:

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】:

还有这个

public function myFunc(args:Object) {

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

}

并通过myFunc({id:33,name:'jo')调用它

然后您可以传递该对象,或者这与您要查找的内容相距太远?

【讨论】:

  • 不远,传递动态对象或 VO 类是我的第一个解决方法。我很想知道是否有可能。
【解决方案3】:

这让我进行了一项有趣的长期研究!

我发现这个简洁的 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 类可能能够接受它......嗯。

无论如何,我想也许这值得分享。

【讨论】:

  • 在遇到嵌入式 BitmapData 实例化的一些问题后,我今天想起了这个答案。 CS4 似乎需要“new YourBitmap(-1, -1);”构造函数参数,而 CS5 没有 - “new YourBitmap();”。有点无关紧要,但我开始想......嗯,也许来自 r1.deval.D 的 SWC 正在愚弄我们认为它可以处理任何数字或构造函数参数。我的意思是......谁知道呢,也许他们只是在内部使用 Patrick 的方法(基于参数长度的硬编码构造函数参数)。真的很想提取他们的代码,看看 dEval 是如何做到这一点的。
  • D.eval 将只处理 20 个参数。尽管图书馆很复杂,但他们正在做与原始问题建议的完全相同的事情。这就是 CallExpr.newInstance() 正在做的事情。随意使用具有 20 多个参数的类对其进行测试。
【解决方案4】:

我也在寻找答案,但很遗憾看到答案是否定的......

这是我目前(不太好)做这种事情的方法,希望你们中的一些人感兴趣:

// 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");
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    相关资源
    最近更新 更多