Squeak Smalltalkでクラスを短めの式で生成する

  • 4
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Smalltalk ではクラスを生成するときも、将来のスーパークラスに対するメッセージ送信で行ないます。

Object subclass: #Foo
   instanceVariableNames: 'instVar1 instVar2'
   classVariableNames: 'ClassVar1 ClassVar2'
   poolDictionaries: 'PoolVarDict'
   category: 'Category-Name'


メッセージングを徹底しているし、伝統的な式でもあるのでこれはこれで嫌いではないのですが、いかんせん長い。クラスブラウザでならともかく、ちょっとしたコードをワークスペースでスクリプトっぽく書き捨てにしたいときや動きを説明したいときに面倒です。

そんなとき、Ruby などのクラス定義(class Foo; end)や、同じ Smalltalk でも Pharo や GNU Smalltalk にある

Object subclass: #Foo

とシンプルに済ませられるのはいいなぁ…と思うわけです。もちろん、Class に

Class >> subclass: name
    
^ self subclass: name instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Unclassified'

などと当該メソッドを追加しておけばそれでおしまいなのですが、なんか負けた気がするので(←意味不明)、そこは余計なメソッドがゴマンとある Squeak 、組み込みのメソッドの組み合わせで、少なくとも冒頭のよりは短くクラスを生成するのに使えるメソッドはないものかと探してみました。


結果、Class>>#newSubclass というよさげなのを見つけました。これはレシーバークラス名に“1”をつけた新しいサブクラスを生成するメソッドです。

Object newSubclass  "=> Object1"


生成するクラスの名前くらいは自由につけたいのでどうにかならないものかとさらに探すと Class>>#rename: というのがあったのでなんとかこれとの組み合わせで目的は達成できそうです。

Object newSubclass rename: #Foo  "=> Foo "

#subclass: のシンプルさには負けますが、読み下してもなんとか意味は通じますし、現状の組み込みのメソッドだけでいけるのは面倒がなくていい感じですね。


引き続きインスタンス変数を定義(追加)したければ、こんなふうに書けます。

Object newSubclass rename: #Foo; addInstVarName: 'bar baz'


悪ノリして、アクセッサーも自動生成(Ruby でいうところの Module#attr_accessor 的な作業)してみましょう。

| Foo |
Foo := Object newSubclass rename: #Foo; addInstVarName: 'bar baz'; yourself.
Browser new setClass: Foo selector: nil; createInstVarAccessors.
Foo new bar: #something; bar  "=> #something"


なんだかよくわかんなくなっちゃいましたね。てへぺろ。

教訓: Smalltalk では素直にクラスブラウザを使うべきです。