unintern でカプセル化を実現
Package を使って private 引数を擬似的に実現する - Shammerismで完全なカプセル化は実現できない、と書いたが、方法が見つかった。setter や getter のみでアクセスできる。
? (defpackage "AAA") #<Package "AAA"> ? (in-package aaa) #<Package "AAA"> ? (defparameter *param* "AAA param") *PARAM* ? (defmethod get-aaa-param () *param*) #<STANDARD-METHOD GET-AAA-PARAM NIL> ? (defmethod set-aaa-param (value) (setf *param* value)) #<STANDARD-METHOD SET-AAA-PARAM (T)> ? (unintern '*param*) T ? (export 'get-aaa-param) T ? (export 'set-aaa-param) T ? (in-package common-lisp-user) #<Package "COMMON-LISP-USER"> ? (aaa:get-aaa-param) "AAA param" ? (aaa:set-aaa-param "Changed AAA param") "Changed AAA param" ? (aaa:get-aaa-param) "Changed AAA param" ? (aaa::*param*) > Error: Undefined function AAA::*PARAM* called with arguments () . > While executing: CCL::TOPLEVEL-EVAL, in process Listener(4). > Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts. > If continued: Retry applying AAA::*PARAM* to NIL. > Type :? for other options. 1 >
unintern を使用すると、unintern されたそのシンボルには直接アクセスできなくなる。
では、unintern したシンボルと同じ名前のシンボルを定義した場合にどうなるだろうか。
? (aaa:get-aaa-param) "AAA param" ? (aaa:set-aaa-param "Changed AAA param") "Changed AAA param" ? (aaa:get-aaa-param) "Changed AAA param" ? (aaa::*param*) > Error: Undefined function AAA::*PARAM* called with arguments () . > While executing: CCL::TOPLEVEL-EVAL, in process Listener(4). > Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts. > If continued: Retry applying AAA::*PARAM* to NIL. > Type :? for other options. 1 > q ? (in-package aaa) #<Package "AAA"> ? (defparameter *param* "This is a param.") *PARAM* ? (aaa:get-aaa-param) "Changed AAA param" ? *param* "This is a param." ?
この結果から、unintern されたのと同じ名前でシンボルを定義しても、後から定義された方は最初に定義したやつとは別のものと言うことになる。