クラスの定義
2007/03/30 (Fri) 22:07:46 JST
オブジェクト指向プログラミングの開発プロセス
オブジェクト指向プログラミングの開発プロセスを大雑把に分けるとこうなります。
- クラスの定義
- インスタンス変数などの定義
- メソッドの実装
- テスト・実行
この繰り返しです。メソッドはクラスに属するので、ほとんどの時間をクラスと格闘することになります。
ただし注意しておかなければならないのは、クラスそのものが動作するのではないということです。実行時に動作するのはあくまでもクラスが生成したオブジェクト (クラスのインスタンス) であり、クラスは雛型に過ぎません。オブジェクトをグループ分けするのに便利だからクラスという仕組みがあるのであって、「はじめにクラスありき」ではないことを念頭に置いておきましょう。
Squeakでのクラス定義
Squeakでは、今までも何度も出てきたブラウザを使ってクラス・メソッドを定義します。外部のテキストエディタも使えないことはありませんが、ブラウザを使うのが最も簡単です。
Stackクラス
それではクラスを定義してみましょう。ここではスタックを作ってみます。Squeakでは配列で代用できるので、スタックそのもののクラスはありません。
まず、練習用のクラスをまとめておくためにクラスカテゴリを追加しておきます。ブラウザを開いて左上のウィンドウを最下部にスクロールし、altキー + 左クリックのメニューから "add item.." を選択します。
表示された入力フォームに "LearnOOP" と入力し、「了解」します。
これでクラスカテゴリを追加できました。下のウィンドウのコードは、クラスを定義するコードの雛型です。これを次のように変更し、altキー + 左クリックのメニューから「了解」を選択します。
Object subclass: #Stack instanceVariableNames: 'array position' classVariableNames: '' poolDictionaries: '' category: 'LearnOOP'
これでStackクラスを定義できました。
定義したインスタンス変数は次の通りです。push/popするとpositionを増減して、(外側から見た) スタックに積まれたオブジェクトの数を調整します。
- array
- スタックの本体。配列。
- position
- スタック最上部の位置。
メソッドは次の基本的な処理を実装します。
- top
- スタックの最上部にあるオブジェクトを返す。
- push
- スタックにオブジェクトを積む。
- pop
- スタックからオブジェクトを1つ取り出す。
実装する前にスタッククラスの使い方を確認しておきます。次のように使います。
|stack| stack := Stack new: 3. "スタックサイズを指定" stack push: 'Hello'. "スタックに積む" stack top. "スタックの最上部にある'Hello'を返す" stack pop. "'Hello'を返し、スタックから取り除く"
続けてメソッドを定義していきます。今まで何度も行った操作については説明を省略します。迷ったらメソッドの定義を参考にしてください。
まずは初期化メソッドを実装します。"initialization" メソッドカテゴリを追加し、 initialize: メソッドを実装します。
initialize: size array := Array new: size. position := 0
ただし初期化メソッドと言っても、何もしなくても呼ばれるわけではなく、オブジェクト生成後に呼び出す必要があります。(言語によってはオブジェクトの生成時に初期化メソッドが自動的に呼ばれます)オブジェクトを生成するメソッドは new ですが、 initialize: に引数のスタックサイズを渡す必要があるので、次の処理を行うメソッド new: を定義します。
- オブジェクトを生成する (new)
- オブジェクトを初期化する (initialize:)
new: はクラスメソッドです。クラスリストの下にある "class" ボタンを選択してから定義しましょう。メソッドカテゴリは "instance creation" としてください。
new: size ^self new initialize: size
さて new: を定義しましたが、new/new: と initialize: ではメッセージを受け取るオブジェクト (レシーバ) が異なります。new/new: は Stack new
のように、クラスに対して送るメッセージです。一方 initialize: ではメソッド内でインスタンス変数を操作していますから、インスタンスに対して送るメッセージです。というわけで、頭の中でレシーバを切り替えながらメソッドを実装し分けることになります。
続けて次のメソッドを定義します。あとはすべてインスタンスメソッドなので、今度はクラスリストの下にあるボタンを "instance" に切り替えてから定義しましょう。
top ^array at: position
at:put: は配列の要素をインデックスで取り出すメッセージです。Squeak (Smalltalk) では他の言語と違ってインデックスを1から数えます。
pop |top| top := self top. position := position - 1. ^top
push: anObject position := position + 1. array at: position put: anObject
ここまで定義できたら、ワークスぺースで次を「式を表示」してみましょう。
|stack| stack := Stack new: 3. stack push: 1. stack push: 2. stack push: 3. stack pop. stack pop. stack top
最初にスタックに積んだ 1 が表示されれば成功です。スタックをインスペクトして、push/popすると中身がどうなるのか確認してみましょう。
開発方法
ここではブラウザを通してクラスを定義してきました。クラスとメソッドを定義したらワークスペースで簡単なサンプルを書いて実行し、再びブラウザに戻って修正・拡張を繰り返します。クラスを中心に据えたオブジェクト指向言語では、これが基本的な開発プロセスになります。
ところで、同じプロセスを通るといっても、Squeakにはいろいろなやり方があります。今回はブラウザとワークスぺースを使ってクラスを定義しましたが、これは他の言語で言えばテキストエディタとコンパイラ・インタプリタを使うようなもので、なじみやすい方法だと思います。次回からSqueakならではの、このほかの開発方法を紹介したいと思います。
まとめ
- クラスべースのオブジェクト指向言語での開発は、クラスの定義とテストを繰り返す。
- 初期化メソッドではクラスとインスタンスが交差する。
- Squeakでの開発方法の一つは、ブラウザでクラスを定義し、ワークスぺースでテストする。
Inverse Pages: クラスとインスタンス Squeakによるオブジェクト指向プログラミング入門