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

标签 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)

使用 CLOS 可以进行这种调度吗?如果是,我应该写什么来代替“subclass of”?

最佳答案

请注意,Common Lisp 具有函数 SUBTYPEP:

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

CL-USER 16 > (subtypep 'c 'a)
T
T

请参阅 SUBTYPEP 的文档对于两个返回值的含义(先说是不是子类型)。类也是类型。

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

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

记住:方法中的继承优于类继承。这意味着要使用继承,您必须传递某个类的实例:

(defmethod fun ((param a))
  (format t "~a is a subclass of A~%" (class-name (class-of param))))

上面采用类 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 > 

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

另一种丑陋的版本是对值进行硬编码:

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

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

关于common-lisp - 如何为给定类的子类专门化泛型函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9544137/

相关文章:

types - 如何在制作实例期间强制检查插槽的类型?

common-lisp - 将循环列表复制到固定长度列表

lisp - cl-who 和格式

common-lisp - sbcl/CLOS 为什么我必须在这里添加一个 "validate-superclass"-Method?

methods - 普通口齿不清 : extract methods from generic function

lisp - 如何使用字符串访问未知实例的插槽?

macros - 引用阅读器宏调用

file-io - 在 Common Lisp 中处理并发文件访问

lisp - 将字符串列表转换为 Common Lisp 中的整数列表

lisp - 如何在lisp中找到一个类的包?