Shammer's Philosophy

My private adversaria

カプセル化された class を定義

unintern でカプセル化を実現 - Shammerismで、package を使って global 変数への書き込みや参照にアクセサが必要なようにしてみた。ただ、package でできたのだから class でもできないか、と思いちょっとやってみた。

? (defclass foo ()
((x)))
#<STANDARD-CLASS FOO>
? (defmethod get-x ((vo foo))
(slot-value vo 'x))
#<STANDARD-METHOD GET-X (FOO)>
? (defmethod set-x ((vo foo) value)
(setf (slot-value vo 'x) value))
#<STANDARD-METHOD SET-X (FOO T)>
? (defparameter *foo* (make-instance 'foo))
*FOO*
? (set-x *foo* 10)
10
? (get-x *foo*)
10
? (slot-value *foo* x)
> Error: Unbound variable: X
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of X.
> Type :? for other options.
1 > q
? (slot-value x *foo*)
> Error: Unbound variable: X
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of X.
> Type :? for other options.
1 > q
? (slot-value *foo* 'x)
10
? (unintern 'x)
T
? (slot-value *foo* 'x)
> Error: #<FOO #x302000D2A2ED> has no slot named X.
> While executing: #<CCL::STANDARD-KERNEL-METHOD SLOT-MISSING (T T T T)>, in process Listener(4).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Try accessing the slot again
> Type :? for other options.
1 > q
? (get-x *foo*)
10
? (set-x *foo* 20)
20
? (get-x *foo*)
20
? 

なんか、色々間違えているなぁ。上の例だと間違いも含めてポイントは以下。

  • slot-value でクラス変数を参照する際は、(slot-value $INSTANCE '$INSTANCE_SLOT) という順番。
  • SLOT は Quote してやらないといけない。
  • unintern した後にできたインスタンス達も slot-value に属性でアクセスできなくなっている。

コード上で、アクセサメソッドが全て定義された後で unintern しないとアクセスできなくなってしまうので、メソッドの定義は完全かを確認できてから unintern するのがよさそうだ。