MOPでちょっと試してみた。
とりあえず陽にmake-instanceしなくてもclass slot(?)にアクセスできます。
ここで作ったmetaclassのslotは、allocationにより使用目的が異なることに注意。
特定classにdedicateなmetaclassとして使うことを前提とする場合は:allocation :classとして、任意の「使いたいclass slot」を定義すれば良い。
一般化して「class slotのあるmetaclass」として使うことを前提とする場合は、:allocation :instanceとして定義すればよい。
(この場合は、foo-class よりも class-slot-stadard-class 等のより適切な名前が欲しいところ)
ただし、metaclassに定義されたclass slotを拡張するにはさらにmetaclassを継承するなり、サンプルコードのようにplistやhashtableで擬似スロットを作る類の工夫が必要となる。
(eval-when (:load-toplevel :compile-toplevel :execute)
#+sbcl (use-package :sb-mop) )
(defclass foo-class (standard-class)
((class-slot :initform nil :initarg :class-slot
:accessor class-slot
:documentation "general class slot" )
(foo-slot1 :allocation :class :initform nil :initarg :foo-slot1
:accessor slot1
:documentation "maybe dedicate slot for class foo" )))
(defmethod validate-superclass ((class foo-class) (super standard-class))
t )
(defclass foo () () (:metaclass foo-class))
(defclass bar () () (:metaclass foo-class))
(defparameter foo (find-class 'foo))
(defparameter bar (find-class 'bar))
(defmethod slot2 ((class foo-class))
(getf (class-slot class) :slot2) )
(defmethod (setf slot2) (newval (class foo-class))
(setf (getf (class-slot class) :slot2) newval) )
(class-slot foo) ; => NIL
(slot1 foo) ; => NIL
(slot1 bar) ; => NIL
(slot2 foo) ; => NIL
(slot2 bar) ; => NIL
(setf (slot1 foo) 100) ; => 100
(setf (slot2 foo) 200) ; => 200
(slot1 foo) ; => 100
(slot1 bar) ; => 100
(slot2 foo) ; => 200
(slot2 bar) ; => NIL
(class-slot foo) ; => (:SLOT2 200)
(class-slot bar) ; => NIL