Diamond Inheritance and the General <Lisp Object System

I am trying to find a solution to a typical diamond inheritance problem in Common Lisp CLOS. The code:

(defclass C1.0 () ... )
(defclass C2.1 (C1.0) ...)
(defclass C2.2 (C1.0) ...)
(defclass C3.0 (C2.1 C2.2) ...)

(defmethod m1 ((obj C1.0)) ...)
(defmethod m1 ((obj C2.1)) ...)
(defmethod m1 ((obj C2.2)) ...)
(defmethod m1 ((obj C3.0))
  ; Here I want to call the C2.2 version of
  ; m1
  ...)

Also suppose that the code C1.0, C2.1 and C2.2 is in a library that I do not have access to, so I can’t change anything. Furthur, suppose that some other classes will also be derived from C2.2, and CANNOT want to call version 2 m2, so I cannot add anything to C2.2 with :before. Use call-next-methodwill cause version C2.1.

Just for clarification, here's how to solve it in Python:

class C1_0 :
  def m1 (self) : ...

class C2_1 (C1_0) :
  def m1 (self) : ...

class C2_2 (C1_0) :
  def m1 (self) : ...

class C3_0 (C2_1, C2_2) :
  def m1 (self) :
    C2_2.m1 (self)     # <-- This is the solution
    ...
+4
source share
3

, CLOS. , CLOS , , , . . , , , ( - ).

, :

(defmethod m1 ((obj1 C1.0) (obj2 C1.0)) ...)
(defmethod m1 ((obj1 C2.1) (obj2 C1.0)) ...)
(defmethod m1 ((obj1 C2.2) (obj2 C3.0)) ...)
(defmethod m1 ((obj1 C3.0) (obj2 C3.0)) ...)

, , , . CLOS call-next-method. ( :before, :after :around, ).

() , +, progn and? + .

, :

(defmethod m1 + ((obj1 C1.0) (obj2 C1.0))  1)
(defmethod m1 + ((obj1 C2.1) (obj2 C1.0))  2)
(defmethod m1 + ((obj1 C2.2) (obj2 C3.0)) 10)
(defmethod m1 + ((obj1 C3.0) (obj2 C3.0)) 20)

, , . CLOS (: CLOS).

CLOS: , . , . .

, " " CLOS, - CLOS , , CLOS , CLOS . CLOS , . CLOS , , .

+7

Clozure CL, , ( ) Common Lisp.

m2:

(funcall
  (method-function (find-method #'m1 '() `(,(find-class 'C2.2))))
  obj)
0

, :

(defclass c3.2 (c2.2 c2.1)
  ...)

(defclass c3.1 (c2.1 c2.2)
  ...)

(m1 (make-instance 'c3.2)) ; calls the method specialized to c2.2

(m1 (make-instance 'c3.1)) ; calls the method specialized to c2.1
0

All Articles