第22回
■
■SqueakではじめるSmalltalk入門 第22回
■
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回から、先に作成したBankAccountのサブクラスとしてStockAccountを定義します。
預金を扱うBankAccountに対し、今回作成するStockAccountは、株式口座オブジェクトを定義するクラスとして位置づけることにします。簡単のため、扱う株は一種類、つまり株単価は(可変ですが)一意的とします。a StockAccountの振る舞いはa BankAccountとまったく同じです。つまり、メッセージ「deposit: …」で入金し、「withdraw: …」で払い戻しできます。違うのは、内部状態として、株単価と株数を、それぞれインスタンス変数pricePerShare、numSharesに束縛していること、そして出納の際、その金額に見合った株が売買される(保有株数が減ったり増えたりする)ことです。では早速はじめましょう。
まず、思い出していただきたいのは、BankAccountの定義とその手順です。クラスカテゴリペインに新しいクラスカテゴリ「Category-MosaDen」を追加し、その時コードペインに表示されるテンプレートを次のように書き換えることでBankAccountを定義しました。
Object subclass: #BankAccount
instanceVariableNames: 'balance'
classVariableNames: ''
poolDictionaries: ''
category: 'Category-MosaDen'
これは、Objectというクラスに対する「subclass: #BankAccount instanceVariableNames: 'balance' classVariableNames: ''poolDictionaries: '' category: 'Category-MosaDen'」という長いメッセージ送信式になっている話もしました。改めてこのメッセージを読み下すと、Objectというクラスに対して、そのサブクラスとして#BankAccountという名前をこれこれの仕様で作りなさい…ということになります【註】。StockAccountは、BankAccountのサブクラスなのでこの応用で大丈夫ですね。大まかには、レシーバをObjectからBankAccountに、作成するサブクラス名を#StockAccountに、各種仕様を相応しいものに差し替えればよいわけです。
まず、クラスペインで選択されているBankAccountをクリックして選択を解除します。もし、ブラウザを閉じてしまっていたら、BankAccountをbrowse it(cmd+B)して開いてから、改めて選択を解除してください。すると、コードペインにはクラスカテゴリを新設したときと同様にクラス定義用のテンプレートが現われます。これを、先の方針にしたがって書き換え、accept (cmd+S)します。
BankAccount subclass: #StockAccount
instanceVariableNames: 'pricePerShare numShares'
classVariableNames: ''
poolDictionaries: ''
category: 'Category-MosaDen'
acceptと同時に、クラスペインにStockAccountが追加されます。
[fig.A]StockAccountがクラスペインに追加されたところ
手始めに、お馴染みのアクセッサを定義しましょう。インスタンス変数pricePerShare、numSharesと同名のゲッター(値を取得するためのメソッド)と、引数をひとつ取る、つまりコロンを付したセッター(値設定用のメソッド)を定義します。まず、メソッドカテゴリを新設します。
メソッドカテゴリペインの黄ボタンメニューから「new category...」を選び、続けて現われるポップアップから「accessing」を選びます。このポップアップには、Object以外のスーパークラスで使用済みのメソッドカテゴリが一覧でき、新規カテゴリ名として採択できるようになっているので、スーパークラスのメソッドカテゴリと同様のカテゴリを追加するときは、new...でいちいち再入力せずに済ませることができます。
accessingカテゴリ追加と同時に、下のコードペインにはメソッドテンプレートが選択状態になって現われるので、マウスカーソルをコードペインに移動してアクティベート(選択状態を確認)した後、次のコードをこのメールからコピー&ペーストします。念のため忘れずにシフト黄ボタンメニューからpretty printしてから、accept (cmd+S)して登録します。
pricePerShare: aNumber
pricePerShare _ aNumber
次は#numShares:ですが、ここで、ちょっとした編集テクニックを紹介します。#numShares:の定義は次のようなものです。
numShares: aNumber
numShares _ aNumber
これは先の#pricePerShare:において「pricePerShare」を「numShares」に全置換したものと同一です。そこで、先頭の「pricePerShare」を選択して「numShares」と入力して置き換えた後、続けて、cmd+Jとタイプしてみてください。これはagainと呼ばれるSmalltalkシステムに特徴的なテキスト編集機能で、直前の置き換え操作を次の出現箇所に適用します。大変便利な機能なのですが、残念ながらMacに継承されることはありませんでした。なお、置き換えたい箇所が残り2カ所以上ある場合は、cmd+shift+Jとタイプします。
ゲッターは、BankAccount >> #balance同様、遅延初期化にしておきましょう。numSharesは未定義時、balance同様に0でよいのですが、pricePerShareは0というわけにはいかないので、適当に30くらいにしておきます。
pricePerShare
^ pricePerShare ifNil: [pricePerShare _ 30]
numShares
^ numShares ifNil: [numShares _ 0]
次回は、#balance:、#balanceを再定義してStockAccountを完成させます。
註:記憶力の良いかたは、スーパークラスがサブクラスを作成することに対して、さっそく疑問を持たれたことと思います。なぜなら、クラスはメタクラスのインスタンスであり、サブクラスを作るにしても、そのメタクラスにnewを送信するのがスジで、継承関係こそあれ、赤の他人のスーパークラスがサブクラスを生じさせるのは相応しくない…と考えることができるからです。
結論から申し上げるとその考え方で合っています。ただ、サブクラス定義時点では、サブクラスのメタクラスは存在せず、まずこれから作る必要があります。メタクラスのクラスはMetaclassなので、これのインスタンスとしてStockAccount classがまず生じ、そこから改めてStockAccountが作成されます。スーパークラスへのメッセージ送信はこうした一連の作業のきっかけ作りに過ぎないのです。
このページを編集 (5263 bytes)
|
以下の 1 ページから参照されています。 |
This page has been visited 1034 times.