next up previous
Next: 15.5 メソッドの探索 Up: 15 CLOSのクラスシステムの実現 Previous: 15.3 メソッドの実現

15.4 Instance生成

インスタンスの生成というのは,クロージャの生成になります. 関数instanceは以下のように,クラス名と初期メッセージ(args)を 与えると(self x &rest args)という引数を受けとるクロージャを 返します. クロージャに保存される局所変数は, (cls-local-variables (get-class class-name)) です.つまり,クラスに宣言されているインスタンス変数のリストが クロージャ定義のlet文の局所変数宣言のところに渡されます.

(defun make-instance* (cls-name)
  (let ((class (get-class cls-name)))
    (create-instance cls-name
                     (cls-local-variables class)
                     (cls-accessors class))))

(defun create-instance
  (cls-name vars&values vars&accessors)
  (eval `(internal-create-instance
          ,cls-name
          ,vars&values ,vars&accessors)))
;;;
;;; Including instance-variable accessor version
;;;
(defmacro internal-create-instance
    (cls-name vars&values vars&accessors)
  (let ((lambda-parameter (gensym)))
    `(let ,(cons '(var-store (make-hash-table))
            vars&values)
       (setf (gethash 'class var-store)
             #'(lambda () ',cls-name))
       ,@(mapcar
          #'(lambda (var&accessor)
              `(setf (gethash ',(cadr var&accessor)
                                var-store)
                 #'(lambda () ,(car var&accessor))) )
          vars&accessors)
       ,@(mapcar
          #'(lambda (var&accessor)
              `(setf (gethash ',(caddr var&accessor)
                               var-store)
                 #'(lambda (,lambda-parameter)
                     (setf ,(car var&accessor)
                       ,lambda-parameter))) )
          vars&accessors)
       #'(lambda (self x &rest args)
           (let
            ((local-var-function (gethash x var-store)))
            (if local-var-function
                (apply local-var-function args)
              (let ((method (find-method* x ',cls-name)))
                (if method
                    (apply method (cons self args))
                  (error
                    "~a undefined method for class ~a"
                    x ',cls-name)))))))))
クロージャは,送られてくるメソッドがクラス(class-name)に 登録されているかどうか探しだし(find-method),そのメソッドが あればそれを実行する,というように作ります. make-instance*はスロットの初期化引数などはとれない形になって います.

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