lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Am 27. April 2011 21:29:49 UTC+2 schrieb Lorenzo Donati
<lorenzodonatibz@interfree.it>:
> Hi all!
>
(...)
>
> That is I make use of the follwing:
> - a shared metatable for all objects of the same kind
> - proxy tables
> - the actual object is stored in the proxy table using a "private" index
> (the metatable itself) to achieve encapsulation and prevent the client from
> tampering with the object directly.
>
> Note: I don't need inheritance support, since almost always use this pattern
> to represent objects of "concrete classes".
>
> I'm still a bit puzzled at the plethora of possible approaches, and I'm
> still exploring, so I will greatly appreciate some comments.
>
> In particular, is this kind of approach acceptable, i.e, is it sound enough
> or am I missing something? Are there some obvious drawbacks of such a design
> pattern?
>
> Thanks in advance for any help.
>
> P.S.: I've browsed the WIKI and this approach doesn't seem to be there.
> It is in part based of a suggestion given in PiL (section 13.4.4 - Tracking
> Table Accesses). I've also searched the list archive for "proxy tables", but
> the results where overwhelming and I didn't find anything close to what I'm
> using - thus my doubts.
>
>
> -- Lorenzo
>
>
>
>
>
>

Proxy tables are awkward to work with - iterating it becomes
complicated, it's sometimes confusing to work with it and the
performance is bad.
The problem with the lack of access control is this: In OO languages,
you usually have means to access values of super classes that are
otherwise denied (=protected). If you hide values in Lua, you can't
access the variables from any other locations than in the code you've
written. This is the biggest drawback in my opinion.

I found this here the most useful:

entity = {}
entity.__mt = {__index = entity,__tostring=function(o) return o:tostring() end}
function entity:new(type)
  return setmetatable({type=type},self.__mt)
end
function entity:tostring() return "["..self.type.."]" end

player = setmetatable({},{__index = entity})
player.__mt = {__index = player, __tostring=player.__mt.tostring})
function player:new() return entity.new(self,"player") end

print(player:new())

-- 

The reason why I find this most useful is this:
- it works with stock Lua right out of the box - not even helper
functions are needed
- it's relatively short - the class initializing is most typing but is
usually also not so much work
- it allows reusing constructors of super classes since the
constructor isn't bound to it's actual class it's defined in
- since it's stock Lua, any other Lua programmer should understand it
quite quickly - especially since it's short
- it's the most efficient OO pattern I have found so far - mostly
because it's the most simple one
- since all your OO functions use the : for calling, there's less
confusion about whether to use . or :
- if you really want to have real "private" variables with access
control, you can use closures, e.g.
function player:new()
  self = entity.new(self,"player")
  local id = math.random() -- some uid code
  function self:getId() return id end
  return self
end
-- note: Using closures involves much more processing powers, so use
them wisely if it's time critical code. But it's more efficient than
proxy tables.
-- note2: You can have "static" private data by surrounding your class
code with "do..end" and use local variables within the functions


So in short: I think this is the most simple and most efficient OO
pattern in Lua while still providing a great deal of flexibility
through metatable programming if you really need it.

Cheers,
Eike