关于 apache flex:ActionScript 上的可调用对象?

Callable objects on ActionScript?

是否可以在 ActionScript 上使用可调用对象?例如:

1
2
3
4
5
6
7
8
9
class Foo extends EventDispatcher
{
  Foo() { super(); }

  call(world:String):String
  {
    return"Hello," + world;
  }
}

后来……

1
2
var foo:Foo = new Foo();
trace( foo("World!") );    // Will NOT work

一种选择是使用闭包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function Foo():Function {
    var bar:String;
    return function (world:String):String {
        var msg:String;
        if (bar) {
            msg = bar + ' says"Hello, ' + world + '"';
        } else {
            msg ="Hello," + world;
        }
        bar = world;
        return msg;
    }
}
...
var foo = Foo();
trace( foo("World!") );

这是将对象实现为函数的更大模式的一个非常简化的案例。因此,它在支持 FP 但不支持 OOP 的语言中更有用,但在技术上确实为您提供了可调用的"对象"。语法可能有点偏离,但是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public function createFoo(barInit, ...):Function {
    var slots = {
        greeter: barInit, ...
    };
    var methods = {
        'get': function(name) { return slots[name]; }
        'set': function(name, value) { slots[name] = value; }
        greet: function(whom) {
            var msg = slots.greeter + ' says"Hello, ' + whom + '"'
            slots.greeter = whom;
            return msg;
        },
        ...
    };
    return function (method:String):* {
        args = Array.splice.call(arguments, 1);
        return methods[method].apply(null, args);
    }
}

var foo = createFoo('Kermit');
trace(foo('greet',"World"));
trace(foo('greet',"Sailor"));

你可能不想在 AS 中这样做。


正如其他人所说,您不能拥有可调用的对象。但是,如果由于某种原因你想要有状态的函数,你可以借助静态类变量和包级函数来实现它。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// com/example/foo/Helper.as
package com.example.foo {
    public class Helper {
        private static var _instance:Foo;

        public static var data:String;

        public static function get instance():Helper
        {
            if(!_instance) { _instance = new Helper(); }
            return _instance;
        }
    }
}

// com/example/foo/hello.as
package com.example.foo {
    public function hello(world:String):void
    {
        if(Helper.instance.data)
        {
            trace("Bye," + Helper.instance.data);
        }
        trace("Hello," + world);
        Helper.instance.data = world;
    }
}

使用时会打印不同的东西。

1
2
hello("World!");   // traces"Hello, World!"
hello("People");   // traces"Bye, World!" and"Hello, People"

不可以,只能以这种方式调用函数/方法。如果唯一的原因是您想输入更少的字符,那么您应该缩短实例名称和方法名称的长度。


您为什么需要这样做? (我不是批评,只是感兴趣!)AS3 中的函数本身就是一等公民,可以作为参数传递。

例如

1
2
3
4
public function main(foo:Function):void
{
    trace(foo("World!")); // Will work, assuming foo = function(str:String):String {...}
}


注意:构造函数和方法声明都错过了关键字 public function 甚至无法编译,但我想那不是原始代码。 :)

答案是:你不能。
我的问题是:你想完成什么?

Function 是唯一可调用的值。而且 Function 是 ActionScript 中的原语,与 intBoolean 非常相似,因此没有有意义的方法来扩展它们。

如果你想让它成为一个对象,就用Java的方式,定义一个ICallable接口,然后实际调用一个方法,或者只是真正使用一个函数。如果您想要的话,闭包提供了创建有状态函数的最简单和灵活的可能性。

编辑:好吧,你可以这样做(例如):

1
2
private var fooInst:Foo = new Foo();
protected var foo:Function = fooInst.call;

然后按照您的意愿执行以下操作:

1
<mx:Label text="{foo('Whatever')}"/>

它甚至可能更灵活一点,尽管你失去了严格输入的好处。

问候
back2dos