第3回 小レポートについて(クッキーの話)

Smalltalk の総合練習の回答のポイントを説明します。

なお、今回の採点については、授業・演習の短い時間では思いつかないことなので、下記のことまで考慮していない回答に対しても 10 点をつけています。

■ メソッド内で処理が完結すべき

次のようなプログラムが回答に多く見られました。このプログラムの問題点は、メソッド price が正しく動作するためには、その直前までにメソッド size が実行済みでなければならないことです。もし、size が実行されずに price が実行されると、正しい結果の得られる保証がありません。
※ mysize をインスタンス変数とする。

size
  mysize := hankei * hankei * 3.14
  ^ mysize

price
    ^mysize * 3

showPrice
  - (中略) -
  sum := 0
  self do: [: c |
     c size
     sum := sum + c price
  ]
  - (中略) -

では、どうすべきであったのでしょうか。メソッド price は、メソッド size を呼び出して、その結果に定数の 3 を掛けて出力するべきでした。つまり、以下のように price を定義し、showPrice から「c size」をカットすれば良いのです。
price
    ^self size * 3

■ オブジェクト間で共通するものは、上位オブジェクトが担当すべき

オブジェクトの上下関係は、どのように利用すべきでしょうか。下位オブジェクトの間で共通する変数やメソッドは、上位オブジェクトが持つべきです。今回、丸クッキー、三角クッキー、四角クッキーの間で共通する変数は、製造日です。なので、製造日についてのアクセサ pdate および pdate: は、上位オブジェクトである MyCookie が持つべきです。

さて、実は他にも共通することがあります。それは、価格の出し方です。面積の 3 倍という計算の仕方は、今回のクッキーの間で共通しています。したがって、次のように、メソッド price を MyCookie のクラスで定義すると良いのではないか、という考えに至ります。

ここで、擬似変数 self が使えるのか心配になると思います。MyCookie だけ見ていると不安になりますが、MaruCookie オブジェクトなど下位オブジェクトのインスタンスの立場で考えてみると都合良く動作しそうです。

つまり、MaruCookie オブジェクトのインスタンスは、メソッド中の self という記述については、自分自身として解釈します。self の記述されたオブジェクトの上位・下位に関わりません。MyCookie のメソッドであっても自分自身が MaruCookie なので、self size といえば、MaruCookie の size のことになります。

■ コレクションの便利なメソッドについて

Bag の中から最小値を抽出するためには、min が使えます。たとえば、下記を実行してみましょう。
> a := Bag new
> a add: 1
> a add: 5
> a add: 3
> a min
> a max

したがって、showBestBeforeDay においては、自身(MyCookieBag)の持つ各要素の製造日を一時的なバッグに入れておき、min を使って最小値を抽出すれば良いのです。


(C) 2007.5.29 by tokuhisa