【问题标题】:Can you store functions in variables?您可以将函数存储在变量中吗?
【发布时间】:2019-05-03 11:59:35
【问题描述】:

我目前正在学习一点 Smalltalk。

有没有一种方法可以将函数或方法存储在变量中?

例如,在 Python 中可以说:

x = someobject.method
x() # calling it

这在 Smalltalk 中可行吗?将something.method 本身作为参数传递给另一个方法怎么样?

【问题讨论】:

  • 正如安德烈在他的(优秀)回答中清楚地解释的那样,这种可能性是存在的。但是,除非您做一些不寻常的事情,否则您通常会使用 blocks,而不是 compiled methodsselectors。使用perform 可能表明设计不佳。

标签: methods message smalltalk


【解决方案1】:

您可以通过向类对象询问具有给定名称的方法来获取方法对象。在>> 下方是一条消息发送到Object 类,其中方法名称作为参数。

Object >> #asString

这将返回一个CompiledMethod 类型的实例。这是一个表示方法的对象。像任何对象一样,您可以将其存储在变量中。

copyMethod := Object>>#asString.

例如,如果您在 Pharo 中打开一个 Playground 并检查上面的代码,您会得到:

executing code in playground

然后您可以使用消息#valueWithReceiver:arguments: 执行该方法。这需要接收者(self/this)和可能的参数作为参数。

result := copyMethod 
    valueWithReceiver: Object new arguments: #().

executing the method

但是,这是执行方法的低级方式。

我想说更常见的是直接在对象上执行具有给定名称的方法。这可以使用perform:perform:withArguments: 来完成。您可以将此方法名作为参数发送给对象

receiver := Object new.
receiver perform: #asString.

上面的代码在接收者对象上执行名为asString的方法。这通常用于传递我们需要执行的方法的名称。不同之处在于CompiledMethod 的实例是不可变的。如果您更改该方法的代码,则会创建一个新实例,您最终可能会执行该方法的旧版本。

【讨论】:

    【解决方案2】:

    通常,您在 Smalltalk 中应该做的就是发送消息。你永远不会执行一个方法,因为它违反了封装并且通常不是正确的抽象级别。

    当你发送消息时,接收者对象在它的类methodDictionary中查找用于关联一个CompiledMethod到消息选择器,如果没有,它然后在超类methodDictionary中查找,等等......或者如果没有对应的方法,最后发送dosNotUnderstand:消息被发现。所有这些机器都在 VM 中执行。这不是程序员的工作。

    当你想发送一个变量的消息时,你可以使用perform:perform:with:perform:withArgument:@andrei-chis 解释。

    selector:= #(printString storeString asString) at: index.
    ^self perform: selector
    

    为了访问低级机器,我们可以通过发送消息valueWithReceiver:arguments: 直接调用该方法,但我强烈建议不要使用它...这种对低级机器的访问专用于调试支持,因为我说不是正确的抽象级别 - 除非您尝试在 Smalltalk VM 之上实现另一种语言并寻求这样的低级构造。

    如果你忽略了这个警告,那么你有责任提供一个正确类的实例作为接收者(或者如果你想破解,至少提供一个为实例变量等分配足够空间的对象......) .这样做的失败率最低,而且您可能会损坏对象内存并让 VM 迟早崩溃,如果您有时间在致命崩溃之前保存损坏的映像,则会丢失一些工作......

    总之,考虑向对象发送消息而不是调用方法;让对象自己决定执行哪个方法,这不关我们的事,Smalltalk 一直是消息。

    【讨论】:

      猜你喜欢
      • 2010-12-02
      • 1970-01-01
      • 2019-06-09
      • 2013-05-18
      • 1970-01-01
      • 2020-05-18
      • 2022-11-17
      • 2012-10-30
      • 1970-01-01
      相关资源
      最近更新 更多