3

Common-Lisp CLOS で

既存のクラスにもう 1 つのスーパー クラスを動的に追加することは可能ですか。

アップデート:

同じ引数を使用してメソッド/関数にいくつかの動作を関連付けるdefassocのようなマクロを定義したかった

例えば

(defassoc (gname (s (g group)))
    ((name1 (name ((corresponding-task task g) s)))
     (record1 (record ((corresponding-task task g) s))))
  (let ((n name1)
        (r record1))
    (if (and name1 record1)
        (display name1 record1)
        (call-next-method))))

に展開

(symbol-macrolet ((name1 (name ((corresponding-task task g) s)))
                  (record1 (record ((corresponding-task task g) s))))
  (defmethod gname :after (s (g group))
            (let ((n name1) (r record1))
              (if (and name1 record1)
                  (display name1 record1)
                  (call-next-method)))))

ここでは、 (gname (s (g group)) が呼び出されたときに、対応するタスクをグループに呼び出す必要があることを確認しています

(name ((corresponding-task task g) s)
(record ((corresponding-task task g) s)

このマクロを使用しました

(defmacro defassoc ((main-method main-method-lambda-list)
                    funspec-list &body body)
  `(symbol-macrolet ,(mapcar (lambda (fspec)
                               (destructuring-bind (name f) fspec
                                 (list name f)))
                             funspec-list)
     (defmethod
       ,main-method ,mod ,main-method-lambda-list
       ,@(if body
             body
             `(if (and
                   ,@(mapcar (lambda (e)
                               (car e))
                             funspec-list))
                  (call-next-method)))))

しかし、問題はそれが上書きされることです

(defmethod gname :after (s (g group))
      ...)

(ある場合は、あるかどうかを確認できます。)

しかし、上書きするメソッドがあるかどうかに関係なく、どのオブジェクトでも機能するようにしたい

したがって、基本的に、そのクラスとメソッドのコードを変更する必要があります。

したがって、親クラスを動的に追加してこのメ​​ソッドを定義することを決定した方法の1つです。

別の方法としてdefadvideまたはfwrapperを使用できますが、SBCLにはありません。

4

1 に答える 1

3

はい、可能です。最も簡単な方法は、単にクラスを再定義することです。これを行うには、 への別の呼び出しを発行しDEFCLASSます。もっと複雑なことをしたい場合は、MOP (MetaObject Protocol) に頼る必要があります。基本的に、あなたがやりたいことはすべて MOP を使用して可能ですが、さらに説明するには、あなたが何をしようとしているのかについて、より詳細な情報が必要です。

于 2011-08-15T15:40:10.123 に答える