【问题标题】:how to define and call class methods in common lisp / CLOS常见的lisp/CLOS中如何定义和调用类方法
【发布时间】:2016-02-17 16:14:24
【问题描述】:

我想在类对象上定义方法,这些方法基于类的祖先继承,就像实例的方法继承一样。有没有办法做到这一点?

以下是不起作用的:eql-method 专业化。考虑这个例子:

(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

我想在birdanimal 上定义“方法”,这样当我在(find-class woodpecker) 上调用wings-p 时,wings-p 返回t

我觉得这是几乎所有其他 OO 系统的标准功能,但我不记得如何使用 CLOS 来做到这一点。

【问题讨论】:

  • 这在 Java、C# 或 C++ 中不是标准的,静态方法在逻辑上是等效的。在这些语言中,您必须指定另一个类,即使它恰好是基类。

标签: oop common-lisp clos ansi-common-lisp


【解决方案1】:

(find-class 'bird)(find-class 'woodpecker) 返回的对象之间确实没有直接的继承链接,正如您不能期望仅在 (eql 1)(eql 2) 上专门化的泛型函数在给定值 3 时会产生结果.

在您的情况下,您可以从STANDARD-CLASS 派生元类。 您还需要为VALIDATE-SUPERCLASS 定义方法,然后您可以定义您自己的具有适当:metaclass 参数的类。例如(find-class 'animal) 将返回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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 2012-12-10
    • 1970-01-01
    相关资源
    最近更新 更多