1

これが可能かどうかはわかりませんでしたが、(かなり醜い) 回避策を使用しました。

以下のようなクラス構造があるとします。

(defclass a () ())
(defclass b (a) ())

そして方法:

(defmethod print-object ((a1 a) stream)
 (format stream "instance of A "))

ここで、「型キャスト」関数が存在すると仮定して、'a に対して print を呼び出し、次に 'b に対して print を呼び出したいと思います。

(defmethod print-object ((b1 b) stream)
 (prin1 (type-cast b1 'a) stream)
 (format stream "instance of B "))

私の回避策は、b の print-object 内にタイプ a のオブジェクトを作成してから、prin1 を呼び出すことです。

(defmethod print-object ((b1 b) stream)
 (let ((a1 (make-instance 'a)))
    (prin1 a1 stream))
 (format stream "instance of B "))

私は強制しようとしましたが、無限ループになってしまいました。find-method と call-method を試してみることができることに気付きました (うまくいきますか?)。または、:around で解決策を試す必要がありますか?

4

3 に答える 3

6

COERCECLOS オブジェクトでは機能しません。を使用してインスタンスのクラスを変更できますがCHANGE-CLASS、通常はお勧めできません。

CALL-NEXT-METHOD

次の該当するメソッドを呼び出すことができます: CALL-NEXT-METHOD. そのように特定のメソッドを呼び出すことはできず、次のメソッドだけを呼び出すことに注意してください。ほとんどの場合、これは CLOS で使用されるものです。:aroundタスクは、メソッドの定義中に、プライマリ、、:beforeおよび:afterメソッドを使用して、正しい動作が現れるようにジェネリック関数をセットアップすることです。

他のすべてが失敗したときに特定の関数を呼び出す

特定のメソッドを呼び出す難解な方法があります。

(funcall (method-function (find-method #'print-object
                                       nil
                                       (list (find-class 'a)
                                             (find-class t))))
         (make-instance 'b)
         t)

上記のコードでは、関数METHOD-FUNCTIONは ANSI Common Lisp の一部ではありませんが、Metaobject Protocol (MOP)によって多くの実装で提供されています。

于 2013-12-26T07:28:56.487 に答える
6

Coerceb1 にはすでにタイプ (サブタイプ) があるため、新しいオブジェクトは作成されませんa

必要なのは次のcall-next-methodとおりです。

(defmethod print-object ((a1 a) stream)
   (format stream "instance of A "))

(defmethod print-object ((b1 b) stream)
   (call-next-method) ; by default same arguments are used: b1 and stream
   (format stream "instance of B "))
于 2013-12-26T03:26:41.670 に答える
0

Sonya Keene によるプロセス ロックの例 (COMMON LISP のオブジェクト指向プログラミング: CLOS のプログラマー ガイド) に従って、:after メソッドを使用できます。

(defmethod print-object ((a1 a) stream)
  (format stream "instance of A ")) 
(defmethod print-object :after ((b1 b) stream)
  (format stream "instance of B "))

これにより、

CL-USER> (make-instance 'b)
    instance of A instance of B 
于 2013-12-29T14:22:25.873 に答える