我想在类对象上定义方法,这些方法基于类'而继承。祖先与实例相同的方式'方法继承。有没有办法做到这一点?
这里有什么不起作用: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
,您可以看到为什么 - 类woodpecker
显然不是eql
任何方法专精。
我想定义"方法"在bird
和animal
上,以便当我在wings-p
上致电(find-class woodpecker)
时,wings-p
会返回t
。
我觉得这是几乎所有其他OO系统的标准功能,但我无法记住如何使用CLOS。
答案 0 :(得分:4)
(find-class 'bird)
和(find-class 'woodpecker)
返回的对象之间确实没有直接的继承链接,正如您不能指望专门用于(eql 1)
和(eql 2)
的泛型函数一样给定值为3时的结果。
在您的情况下,您可以从STANDARD-CLASS
派生元类。
您还需要为VALIDATE-SUPERCLASS
定义方法,然后您可以定义具有相应:metaclass
参数的自己的类。例如,(find-class 'animal)
将返回animal-class
的实例。
然后,您将专注于(eql (find-class 'animal))
,而不是专注于animal-class
。更确切地说:
(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