2016-06-15 3 views
4

私がきしむ音でプログラミングし、次のように2つのコードブロックを比較する必要があるのです:(toRunBlockはインスタンス変数である)比較ブロック

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

しかし、いくつかの点で、私は別のものにそれを比較する必要がありますコードのブロック:

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

しかし、そのチェックは常にfalseを与えている、と私は、彼らが同じだかどうかを確認する方法を見つけることができません。誰かがこれで私を助けることができますか?

+4

なぜ2つのブロックを比較する必要がありますか?モデリングの問題ではありませんか? –

答えて

6

@LeandroCanigliaが指摘しているように、ブロックを比較する必要はありません。ここでは、ブロックを比較することなく、あなたの問題を解決するには2つの方法がある:

  1. nilに変数を初期化します。あなたのアクセサメソッドでは、遅延し、それを初期化する:あなたは、変数toRunBlockを見たとき#toRunBlockが送られたかのようにブロックが他の手段によって設定されていない限り

    toRunBlock 
        ^toRunBlock ifNil: [ [] ] 
    

    は今、それはnilになります。

    あなたのコードはなる:

    toRunBlock ifNil: [ 
        "Run some code if toRunBlock hasn't been overwritten" 
    ]. 
    
  2. あなたがチェックすることができインスタンス変数を設定することで、追加の状態を使用します。これは、例えば、あなたのセッターメソッドのようになります。

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

    そして、あなたは、このような方法で使用することができますチェックする:あなたのコードになるでしょう

    hasToRunBlockBeenSet 
        ^hasToRunBlockBeenSet ifNil: [ false ] 
    

    を:

    self hasToRunBlockBeenSet ifTrue: [ 
        "Run some code if toRunBlock hasn't been overwritten" 
    ]. 
    

間違いなく信頼性の高い方法です。

3

参照の等価性を除いて、等価はBlockClosuresには定義されていません。 2つのブロックは同じように動作するかもしれませんが、コードの断片だけでなくクロージャであるため、ブロックはまだ異なります。各ブロックには、コンテキストが作成されたコンテキスト(メソッドのアクティブ化または別のブロック)への参照があるため、2つの[nil]は少なくともこの点で異なります。

ブロックがまだであるかどうかを確認するには、以前と同じを別の場所に保存してください。あなたのケースでは[nil]が何らかのデフォルト値であると仮定すると、その[nil]ブロックを別のインスタンス変数またはクラスプール変数(たとえばdefaultRunBlock)に格納し、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