Applescript - 运行 列表中的处理程序

Applescript - running handlers from a list

我正在 applescript 中试用这段代码:

第一个有效,第二个无效

global theOpts
on saySomething()
--some code that it runs
end 

set theOpts to {saySomething}

--the one that does

set t to theOpts's item 1
t()

--the one that doesn't

on runByIdx(idx)
    set thefun to item 1 of theOpts
    thefun()
end runByIdx

有什么方法可以让它发挥作用吗?

总而言之,我想做的是有一个处理程序列表,我可以按索引而不是按名称调用这些处理程序。

这两种方式都有效...

global theOpts
on saySomething()
    return 1
end saySomething

set theOpts to {saySomething()}

--the one that does

set t to theOpts's item 1
--t

runByIdx(1)
on runByIdx(idx)
    set thefun to item idx of theOpts
    thefun
end runByIdx

不要那样做。这是一种未记录的行为和已知的设计缺陷。处理程序并不意味着作为对象进行操作,它会破坏处理程序与封闭脚本的绑定。

正确的做法是将每个处理程序包装在自己的脚本对象中,然后将这些脚本对象放入列表中。

script Foo
    on doIt()
        say "this"
    end doIt
end script

script Bar
    on doIt()
        say "that"
    end doIt
end script

set opts to {Foo, Bar}

doIt() of item 1 of opts

虽然你也不应该低估一个简单的 if...else if... 块的价值:

if idx = 1 then
    doThis()
else idx = 2 then
    doThat()
else ...

基本上这取决于您要解决的问题。但我倾向于后一种方法(即 KISS),除非它是一项需要额外灵活性的任务,否则你只是在增加不必要的复杂性并为自己工作。

(FWIW,几年前我与人合着的 AppleScript book 有一章是关于使用脚本对象的。关于库的部分没有涵盖 10.9+ 中的新库系统,而该部分OOP 上有一个技术错误的软木塞,如果你知道在哪里 look:p,但它可能是对这个主题的最好解释,如果你真的想了解更多,你会发现非常值得一看。)