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 {...} } |
注意:构造函数和方法声明都错过了关键字
答案是:你不能。
我的问题是:你想完成什么?
如果你想让它成为一个对象,就用Java的方式,定义一个ICallable接口,然后实际调用一个方法,或者只是真正使用一个函数。如果您想要的话,闭包提供了创建有状态函数的最简单和灵活的可能性。
编辑:好吧,你可以这样做(例如):
1 2 | private var fooInst:Foo = new Foo(); protected var foo:Function = fooInst.call; |
然后按照您的意愿执行以下操作:
1 | <mx:Label text="{foo('Whatever')}"/> |
它甚至可能更灵活一点,尽管你失去了严格输入的好处。
问候
back2dos