如何在 common lisp / CLOS 中定义和调用 class 方法
how to define and call class methods in common lisp / CLOS
我想在 class 对象上定义方法,这些方法基于 class 的祖先继承,其继承方式与实例方法继承的方式相同。有什么办法可以做到这一点吗?
这是不起作用的:eql
-方法专业化。考虑这个例子:
(defclass animal ()())
(defclass bird (animal)())
(defclass woodpecker (bird)())
(defmethod wings-p ((animal-class (eql (find-class 'animal)))) nil)
(defmethod wings-p ((bird-class (eql (find-class 'bird)))) t)
调用 (wings-p (find-class 'woodpecker))
生成一个 no-method-error
,您可以明白为什么 - class woodpecker
显然不是任何方法专家的 eql
。
我想在 bird
和 animal
上定义 "methods",这样当我在 (find-class woodpecker)
上调用 wings-p
时,wings-p
returns t
。
我觉得这是几乎所有其他 OO 系统的标准功能,但我不记得如何使用 CLOS 来实现。
在由 (find-class 'bird)
和 (find-class 'woodpecker)
编辑的对象 return 之间确实没有直接继承 link,正如您不能指望仅针对 (eql 1)
和 (eql 2)
在给定值 3 时产生结果。
在您的情况下,您可以从 STANDARD-CLASS
派生元classes。
您还需要为 VALIDATE-SUPERCLASS
定义方法,然后您可以定义自己的具有适当 :metaclass
参数的 class。例如 (find-class 'animal)
将 return 是 animal-class
的一个实例。
然后,您将专注于 animal-class
,而不是专注于 (eql (find-class 'animal))
。更准确地说:
(defpackage :meta-zoo (:use :closer-common-lisp))
(in-package :meta-zoo)
(defclass animal-class (standard-class) ())
(defclass bird-class (animal-class) ())
(defclass woodpecker-class (bird-class) ())
(defmethod validate-superclass ((class animal-class)
(super standard-class)) t)
(defclass animal () () (:metaclass animal-class))
(defclass bird () () (:metaclass bird-class))
(defclass woodpecker () () (:metaclass woodpecker-class))
(defgeneric class-wing-p (class)
(:method ((a animal-class)) nil)
(:method ((b bird-class)) t))
(defparameter *woody* (make-instance 'woodpecker))
(class-of *woody*)
;; => #<woodpecker-class woodpecker>
(class-wing-p (class-of *woody*))
;; => t
我想在 class 对象上定义方法,这些方法基于 class 的祖先继承,其继承方式与实例方法继承的方式相同。有什么办法可以做到这一点吗?
这是不起作用的:eql
-方法专业化。考虑这个例子:
(defclass animal ()())
(defclass bird (animal)())
(defclass woodpecker (bird)())
(defmethod wings-p ((animal-class (eql (find-class 'animal)))) nil)
(defmethod wings-p ((bird-class (eql (find-class 'bird)))) t)
调用 (wings-p (find-class 'woodpecker))
生成一个 no-method-error
,您可以明白为什么 - class woodpecker
显然不是任何方法专家的 eql
。
我想在 bird
和 animal
上定义 "methods",这样当我在 (find-class woodpecker)
上调用 wings-p
时,wings-p
returns t
。
我觉得这是几乎所有其他 OO 系统的标准功能,但我不记得如何使用 CLOS 来实现。
在由 (find-class 'bird)
和 (find-class 'woodpecker)
编辑的对象 return 之间确实没有直接继承 link,正如您不能指望仅针对 (eql 1)
和 (eql 2)
在给定值 3 时产生结果。
在您的情况下,您可以从 STANDARD-CLASS
派生元classes。
您还需要为 VALIDATE-SUPERCLASS
定义方法,然后您可以定义自己的具有适当 :metaclass
参数的 class。例如 (find-class 'animal)
将 return 是 animal-class
的一个实例。
然后,您将专注于 animal-class
,而不是专注于 (eql (find-class 'animal))
。更准确地说:
(defpackage :meta-zoo (:use :closer-common-lisp))
(in-package :meta-zoo)
(defclass animal-class (standard-class) ())
(defclass bird-class (animal-class) ())
(defclass woodpecker-class (bird-class) ())
(defmethod validate-superclass ((class animal-class)
(super standard-class)) t)
(defclass animal () () (:metaclass animal-class))
(defclass bird () () (:metaclass bird-class))
(defclass woodpecker () () (:metaclass woodpecker-class))
(defgeneric class-wing-p (class)
(:method ((a animal-class)) nil)
(:method ((b bird-class)) t))
(defparameter *woody* (make-instance 'woodpecker))
(class-of *woody*)
;; => #<woodpecker-class woodpecker>
(class-wing-p (class-of *woody*))
;; => t