24950


変数に対して同じクラスのインスタンスをセットする必要が出てきたとき、下のように泥臭いコードになってしまいます:

[code]

    a1 := TestClass new.
    a2 := TestClass new.
    a3 := TestClass new.
    a4 := TestClass new.
    
[/code]

このように書いてしまうと、同じクラスのインスタンスを代入する行がずっと続くことになり、非常に汚ないように感じてしまいます。もし、このように変数に対して、同じクラスのインスタンスをそれぞれに代入する方法があれば、教えてください。


CC BY-SA 3.0
2016-05-17T14:37:12.937
24941
2018-10-05T06:21:35.947
2018-10-05T06:21:35.947
19110
939
question
smalltalk
変数に対して一度に同じクラスのインスタンスを代入したい


おそらくこういうことだと思うのですが、こうするのがスマートかどうかは微妙ですね。Squeak/Pharo Smalltalk で動作します。

[code]

    | a1 a2 a3 a4 |
    a1 := a2 := a3 := a4 := nil. "コンパイル時の警告抑止のため"
    #(a1 a2 a3 a4) do: [:tName |
       | ctxt tNames |
       ctxt := thisContext outerContext.
       tNames := ctxt tempNames.
       ctxt tempAt: (tNames indexOf: tName) put: tName "実際はTestClass new"
    ].
    ^{a1. a2. a3. a4} "=> #(#a1 #a2 #a3 #a4) "
    
[/code]

* * *

使える変数の数にも限りがあるので、上の @mjy
さんのコメントにもありますが、ひとつのコンテキストで扱うオブジェクトの数が増えてきたら、ひとつひとつを変数にアサインせずに済む方法を考えるのもよいかもしれません。

たとえばゲートの組み合わせて回路を構築するような場面であれば、回路をオブジェクトにしてそれに追加するゲート（名前を付けられるようにしておく）を管理させたり、あるいは各ゲートのクラスに
allInstances で手繰らせるという手もあります。言うまでもなく、名前の衝突については要注意ですが…。

[code]

    NotGate class >> named: gateName
       ^self allInstances
        detect: [:gate | gate name = gateName]
        ifNone: [self new setName: gateName; yourself]
    
[/code]

Squeak/Pharo Smalltalk であれば、named: を implementers of it (alt/cmd + m)
して同名メソッドの定義を一覧すると、（そう多くはないですが）その手の管理方法をとっているオブジェクトの例が見つかるので参考にしてみてください。


CC BY-SA 3.0
2016-05-18T00:06:55.510
24950
2016-05-18T01:48:20.687
2016-05-18T01:48:20.687
15545
15545
24941
answer