如何为给定类的子类专门化泛型函数

Nec*_*cto 3 common-lisp clos

我如何专门化泛型函数来获取指定给定类的子类的符号.例如:

(defclass a () ())
(defclass b (a) ())
(defclass c (b) ())
(defclass d () ())

(defgeneric fun (param))
(defmethod fun ((param (<subclass of> a)))
  (format t "~a is a subclass of A~%" param))

(fun 'c) ;-> "C is a subclass of A"
(fun 'd) ;-> Error: not found method for generic function call (fun 'd)
Run Code Online (Sandbox Code Playgroud)

CLOS可以进行这样的调度吗?如果是的话,我应该写什么而不是" 子类 "?

Rai*_*wig 5

请注意,Common Lisp具有以下功能SUBTYPEP:

CL-USER 15 > (subtypep 'd 'a)
NIL
T

CL-USER 16 > (subtypep 'c 'a)
T
T
Run Code Online (Sandbox Code Playgroud)

有关两个返回值的含义,请参阅SUBTYPEP的文档(首先说明它是否为子类型).类也是类型.

这意味着您的功能就是这样:

(defun fun (class-name)
  (if (subtypep class-name 'a)
      (format t "~a is a subclass of A~%" class-name)
    (error "wtf")))
Run Code Online (Sandbox Code Playgroud)

请记住:方法中的继承适用于类继承.这意味着使用您拥有的继承来传递某个类的实例:

(defmethod fun ((param a))
  (format t "~a is a subclass of A~%" (class-name (class-of param))))
Run Code Online (Sandbox Code Playgroud)

上面是一个类的实例A.

叫它:

CL-USER 29 > (fun (make-instance 'a))
A is a subclass of A
NIL

CL-USER 30 > (fun (make-instance 'c))
C is a subclass of A
NIL

CL-USER 31 > (fun (make-instance 'd))

Error: No applicable methods for #<STANDARD-GENERIC-FUNCTION FUN 418001813C>
with args (#<D 40200011E3>)
  1 (continue) Call #<STANDARD-GENERIC-FUNCTION FUN 418001813C> again
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 32 : 1 > 
Run Code Online (Sandbox Code Playgroud)

有一种方法可以简化^ h ^ h ^ h ^ h ^ h ^ h ^ h ^ h使调用更容易:你可以确保使用类似的东西完成类CLOS:FINALIZE-INHERITANCE并使用类原型作为输入(调用CLASS-PROTOTYPE).这样您就不需要为调度创建类的实例.人们只会使用原型实例.

另一个丑陋的版本是硬编码值:

(defmethod fun0 ((param (eql 'b)))
  T)

(defmethod fun0 ((param (eql 'c)))
  T)
Run Code Online (Sandbox Code Playgroud)