Reputation: 1441
Related question: how do implemented protected members when using the closure approach to OOP?. The problem is most likely the same, although the abstraction that I'm trying to implement is different.
I'm currently implementing a tree structure to represent a scene graph in lua. To do so, lua has several ways of abstracting the concept of classes, and I'm using this one:
new_item = function()
local _self = {}
local _parent = nil
local _children = {}
_self.add_child = function(child)
-- add child to _children
table.insert(_children, child) -- no problems here
-- set child's _parent to _self
child._parent = _self -- this doesn't work: "child._parent" doesn't even exist
end
return _self
end
a = new_item()
b = new_item()
a.add_child(b)
The object returned by new_item
is a table with a single item called add_child
, which is the function I defined. The local variables _self
, _parent
and _children
are local to the scope of new_item
, captured from each "method", and are effectively "private members" of the "class".
Now, to keep the tree consistent, I am creating this function add_child
, which will add the passed parameter (which is expected to be another object created with new_item
) to the list of children of this object, and set the child's parent to this object.
In C++, C# and Java, I have the notion of "private members", and I can access those of a different instance of the same class. In lua though, these local variables are local to the scope of new_item
, so they're not part of the exported object, so I can't access them.
I would like to have a way to implement this abstraction of "accessing private members of a separate instance of the same class", or do something else, so the parent and children links are only modifiable with exported "methods" that can be proven correct.
I think that what I want to do is simply not possible in lua, short of putting _parent
inside of _self
(therefore making it "public"), and asking pretty please for nobody else to touch it, which is, if I'm not mistaken, how Python deals with this.
However, there might be a way of achieving this that I have not thought of, maybe using a different way to abstract the concept of "class". Does anybody know how to go about implementing the abstraction of "accessing private members of a separate instance of the same class" in lua?
Upvotes: 1
Views: 1118
Reputation: 23747
function create_class()
local class = {}
-- when object is garbage-collected, its private data will be auto-removed
local private_data_of_all_objects = setmetatable({}, {__mode = "k"})
function class.create_new_object()
local object = {}
local private = {} -- private fields of this object
private.children = {}
private.parent = nil
private_data_of_all_objects[object] = private
function object.add_child(child)
table.insert(private.children, child)
private_data_of_all_objects[child].parent = object
end
return object
end
return class
end
cl = create_class()
a = cl.create_new_object()
b = cl.create_new_object()
a.add_child(b)
Upvotes: 1