|
On Apr 28, 2011 8:13 AM, "Mark Hamburg" <mark@grubmah.com> wrote:
>
> If your goal is keeping clients from accidentally messing with state, then you can often deal with this with simple naming conventions -- e.g., private fields start with _ or priv_ or whatever.
>
> If you are a little more paranoid and can live with somewhat more typing and a loss in debugger support (or a need for a more sophisticated debugger), then define private keys using tables:
>
> local keyMyPrivateField = {}
>
> self[ keyMyPrivateField ] = 'can't see this'
>
> If you never give out the keys, then clients can't mess with the field contents.
>
> Except, of course, they can if they use pairs or next to iterate the table and recover them. So, that's where you have to decide whether you are concerned with sloppy coding or mischievous coding.
>
> Of course, clients could still go and redefine methods (accidentally), so what you might want to do is keep string keyed values (like methods) in a separate (probably shared) table and use __index and __newindex to access it and to prevent local changes.
>
> Mark
>
> P.S. When I'm in one of my "if only Lua had feature X" moods, one of the things I've thought about is what explicit linguistic support for private keys might look like. My answer was that basically one should be able -- probably with lexical scoping -- to define private keys and whenever a . or : operator is encountered, the system would check to see whether the name used belonged to a currently visible private key and if so would use that value instead of the string. Linguistic support could also mean creating a standard type that would be skipped in tables as a key by next -- something one can do right now by patching next and deciding how to recognize a userdata or table created as a private key.
>
>
Another pattern you can use for private data is a local/hidden table indexed by your object. E.g.:
--myobject.lua
local private = {}
function makeObject()
local obj = {}
private[obj] = {}
return obj
end
function useObject(obj)
local somePrivateValue = private[obj].foo
--...
end
I've left out a lot of metatable stuff like making private have weak keys, giving obj a metatable (real programs should be doing obj:use(), not useObject(obj)) and error checking because writing Lua on my phone is rather difficult :) hopefully you get the idea.
--
Sent from my handheld toaster.