比较Squeak Smalltalk中的块

时间:2016-06-15 20:40:39

标签: smalltalk squeak

我正在使用squeak进行编程,需要比较两个代码块,如下所示:(toRunBlock是一个实例变量)

~~~Other code~~~
toRunBlock := [nil].
~~~Other code~~~

但在某些时候,我需要将它与另一个代码块进行比较:

(toRunBlock = [nil]) ifTrue: [
    "Run some code if toRunBlock hasn't been overwritten"
].

但是这个检查总是假的,我无法找到一种方法来检查它们是否相等。有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:6)

正如@LeandroCaniglia指出的那样,你不应该比较块。以下是两种在不比较块的情况下解决问题的方法:

 
  1. 将变量初始化为nil。在您的访问器方法中,您可以懒惰地初始化它:

    toRunBlock
        ^ toRunBlock ifNil: [ [] ]
    

    现在,当您查看变量toRunBlock时,除非已发送nil或通过其他方式设置了阻止,否则它将为#toRunBlock

    您的代码将变为:

    toRunBlock ifNil: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    
  2. 通过设置您可以检查的实例变量来使用其他状态。这可能是你的setter方法,例如:

    toRunBlock: aBlock
        toRunBlock := aBlock.
        hasToRunBlockBeenSet := true
    

    要检查你可以使用这样的方法:

    hasToRunBlockBeenSet
        ^ hasToRunBlockBeenSet ifNil: [ false ]
    

    您的代码将变为:

    self hasToRunBlockBeenSet ifTrue: [
        "Run some code if toRunBlock hasn't been overwritten"
    ].
    
  3. 第二种方法可以说更可靠。

答案 1 :(得分:3)

除了参考相等性之外,BlockClosures没有定义平等。虽然两个块可能表现相同,但它们仍然不同,因为它们是闭包而不仅仅是代码片段。每个块都引用了创建它的上下文(方法激活或其他块),因此您的两个[nil]在这方面至少会有所不同。

您只能通过存储其他地方之前的内容来检查该块是否仍然与之前的相同。假设[nil]在您的情况下是某种默认值,您可以将[nil]块存储在另一个实例变量或类池变量(例如,defaultRunBlock)中,并将toRunBlock(通过引用)与之比较变量以检查是否已更改toRunBlock。

Object subclass: #YourClass
    instanceVariableNames: 'toRunBlock defaultRunBlock' 
        "or as class variable:"
    classVariableNames: 'DefaultRunBlock'
    poolDictionaries: ''
    category: 'Kernel-Methods'

initialize
    defaultRunBlock := [nil]

otherCode
    toRunBlock := defaultRunBlock

whereYouCompareThem
    toRunBlock == defaultRunBlock ifTrue: [ "..." ]

或者,如果您想检查自上次调用后一种方法后是否更改了toRunBlock,您也可以将之前的值存储在另一个实例变量中。

whereYouCompareThem
    toRunBlock == previousRunBlock ifTrue: [ "..." ].
    previousRunBlock := toRunBlock