Panda Pajama
Panda Pajama

Reputation: 1441

How to access a "private member" of a separate instance of the same "class"?

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

Answers (1)

Egor Skriptunoff
Egor Skriptunoff

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

Related Questions