Anonymous user
Break OO privacy: Difference between revisions
→{{header|Common Lisp}}: Less text, more code.
(→{{header|Common Lisp}}: Break off and extend paragraph on inheritance.) |
(→{{header|Common Lisp}}: Less text, more code.) |
||
Line 188:
The concept of privacy in Lisp is located in the package system. An external symbol S in package P can be accessed using P:S. If S is internal then P:S results in error at read time. This is completely independent of context and orthogonal to the use of symbols to denote class slots (instance variables), methods, functions, class names themselves, global variables, et cetera. Even if the private symbol appears in a literal piece of data like a quoted list, it is an error to refer to it: <code>(1 2 3 P:S)</code>. The internal symbol S in package P can be accessed using <code>P::S</code>. This is easy to do because programmers are assumed to be responsible grownups who can be trusted to know what they are donig. Also, note that this privacy is a property of the relationship between a symbol and a package. A symbol can be present in more than one package, such that it can be internal in some of them, and external in others.
<lang lisp>(defpackage :funky
;; only these symbols are public
(:export :widget :get-wobbliness)
;; for convenience, bring common lisp symbols into funky
(:use :cl))
;; switch reader to funky package: all symbols that are
;; not from the CL package are interned in FUNKY.
(in-package :funky)
(defclass widget ()
;; :initarg -> slot "wobbliness" is initialized using :wobbliness keyword
;; :initform -> if initarg is missing, slot defaults to 42
;; :reader -> a "getter" method called get-wobbliness is generated
((wobbliness :initarg :wobbliness :initform 42 :reader get-wobbliness)))
;; simulate being in another source file with its own package:
;; cool package gets external symbols from funky, and cl:
(defpackage :cool
(:use :funky :cl))
(in-package :cool)
;; we can use the symbol funky:widget without any package prefix:
(defvar *w* (make-instance 'widget :wobbliness 36))
;; ditto with funky:get-wobbliness
(format t "wobbliness: ~a~%" (get-wobbliness *w*))
;; direct access to the slot requires fully qualified private symbol
;; and double colon:
(format t "wobbliness: ~a~%" (slot-value *w* 'funky::wobbliness))
;; if we use unqualified wobbliness, it's a different symbol:
;; it is cool::wobbliness interned in our local package.
;; we do not have funky:wobbliness because it's not exported by funky.
(unless (ignore-errors
(format t "wobbliness: ~a~%" (slot-value *w* 'wobbliness)))
(write-line "didn't work"))
;; single colon results in error at read time! The expression is not
;; even read and evaluated. The symbol is internal and so cannot be used.
(format t "wobbliness: ~a~%" (slot-value *w* 'funky:wobbliness))
</lang>
Output using CLISP:
<pre>wobbliness: 36
wobbliness: 36
didn't work
*** - READ from #<INPUT BUFFERED FILE-STREAM CHARACTER #P"funky.lisp" @44>:
#<PACKAGE FUNKY> has no external symbol with name "WOBBLINESS"</pre>
=={{header|E}}==
|