2016-02-17 74 views
3

我想定義類對象的方法,它們繼承基於類的祖先,就像實例的方法繼承一樣。有沒有辦法做到這一點?如何定義和調用普通的類方法lisp/CLOS

以下是什麼不工作: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任何方法specializers。

我想以定義birdanimal「方法」,這樣,當我打電話wings-p(find-class woodpecker)wings-p回報t

我覺得這是幾乎所有其他面向對象系統的標準功能,但我不記得如何使用CLOS做到這一點。

+1

這在Java,C#或C++中不是標準的,其中靜態方法在邏輯上是等價的。在這些語言中,您必須指定其他類,即使它恰好是基類。 – acelent

回答

4

確實存在通過(find-class 'bird)(find-class 'woodpecker)返回的對象之間沒有直接的繼承鏈,完全按照給定的3

的值時,你不能指望專門只在(eql 1)(eql 2)產生結果的通用功能在你的情況下,你可以從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 
相關問題