next up previous
Next: 11.5 クラスの定義例 Up: 11 データ指向型プログラミング Previous: 11.3 メッセージ送信プログラミング

11.4 Generic Function

メッセージを送るsendを用いるのではなくて,メッセージ名が関数名になる形 にすればlispの関数のように扱うことができるようになる.その第一引数 がオブジェクトで,第二引数以降がメッセージに関連する引数である.そのメッ セージ関数の本体は変わらず,第一引数で与えられるオブジェクトの種類が変 わってもそのオブジェクトからメソッドを取り出して,それに引数を送るとい う形になる.そのような引数のオブジェクトにメッセージを送るだけの関 数の形にしたものはいろいろなオブジェクトを受け付けるため,Generic Functionと呼ばれる. 預金を引き出す,Generic Functionは,

(defun withdraw (object &rest args)
  (apply (get-method object 'withdraw) args))

(defun deposit (object &rest args)
  (apply (get-method object 'deposit) args))

(defun balance (object &rest args)
  (apply (get-method object 'balance) args))
のように定義でき,

> (balance acc)
10.0
> (withdraw acc 3)
7.0
> (deposit acc 5)
12.0
> (balance acc)
12.0
のように使う.このaccの引数に違うアカウント の種類である下のtemp-accountをもってきても

(defun temp-account (&optional (balance 0.00)
                    (interest-rate .06))
  #'(lambda (message)
      (case message
        (withdraw #'(lambda (amt) (decf balance amt)))
        (deposit  #'(lambda (amt) (incf balance amt)))
        (balance  #'(lambda () balance))
        (interest #'(lambda ()
                    (incf balance
                       (* interest-rate balance)))))))

> (setq bcc (temp-account 10.0))
#<Interpreted Closure ...>

> (balance bcc)
10.0
> (withdraw bcc 3)
7.0
> (deposit bcc 5)
12.0
> (balance bcc)
12.0
balance,withdrawなどの同じ関数を用いることができる わけである.これは,このアカウントのデータaccやbcc それぞれがそのデータの中に手続きと個別データを 保存しているから可能になるわけである.

generated through LaTeX2HTML. M.Inaba 平成18年5月7日