On Mar 22, 2009, at 10:27 PM, Mark Engelberg wrote:
>
> I've been thinking quite a bit about the OO side of Clojure the past
> couple of days, and trying to figure out how common OO design patterns
> would look when ported over to Clojure's way of doing things.
>
> The most obvious thing that others have noted is that you can
> effectively simulate a mutable object by having a ref that holds a
> hash map. You can then write getters and setters, and other kinds of
> supporting functions that use and manipulate the ref, and the hash map
> contained therein. But as far as I can tell, there's no way to stop a
> client from simply dereferencing the ref and extracting or
> manipulating the "private" information in the hash map and shoving it
> back into the ref. Even if you trust a client to do the right thing,
> if the object is complex, it might be hard for other programmers to
> figure out which properties are meant to be manipulated, and which are
> "off-limits".
>
> I suspect that if you use double-colon keywords for the keys, you get
> a bit more privacy in the sense that these keys are slightly harder to
> accidentally manipulate from other namespaces, so perhaps that could
> at least be an informal convention for "this is private". Or perhaps
> it's better to keep as much "private" data in the metadata as possible
> (although I would think that in many cases, the private data would
> still be essential to the notion of equality). Any other tricks or
> techniques for helping to hide or separate out the portions of a data
> structure that are meant to be accessed or "altered" from the portions
> that should only be accessed and changed by the existing support
> functions?
>
One simple (simplistic?) way to guarantee privacy is through closures:
(defn make-person [first-name last-name age sex]
(let [age (ref age)]
{:first-name (fn [] first-name)
:last-name (fn [] last-name)
:sex (fn [] sex)
:age (fn [] @age)
:set-age (fn [new-age] (dosync (ref-set age new-age)))}))
person=> (def me (make-person "David" "Sletten" 39 "male"))
#'person/me
person=> ((me :first-name))
"David"
person=> ((me :last-name))
"Sletten"
person=> ((me :age))
39
person=> ((me :set-age) 40)
40
person=> ((me :age))
40
There's no way to manipulate the age ref except through the :set-age
function.
This may not scale though if every 'object' carries around its own
set of all the methods.
Aloha,
David Sletten
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---