如何访问同一“类”的单独实例的“私有成员”?

时间:2018-12-22 05:06:25

标签: lua

Related question: how do implemented protected members when using the closure approach to OOP?。尽管我尝试实现的抽象是不同的,但问题很可能是相同的。


我目前正在实现一个树结构来表示lua中的场景图。为此,lua有几种抽象类概念的方法,而我正在使用这种方法:

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)

new_item返回的对象是一个表,其中包含一个名为add_child的项目,这是我定义的功能。局部变量_self_parent_childrennew_item的范围内是局部的,是从每个“方法”中捕获的,并且实际上是“类”的“私有成员” “。

现在,为了保持树的一致性,我正在创建此函数add_child,它将把传递的参数(预期是用new_item创建的另一个对象)添加到以下子项的列表中此对象,并将孩子的父母设为该对象。

在C ++,C#和Java中,我有“私有成员”的概念,并且可以访问同一类的不同实例的成员。但是在lua中,这些局部变量是new_item范围内的局部变量,因此它们不是导出对象的一部分,因此我无法访问它们。

我想有一种方法来实现这种“访问同一类的单独实例的私有成员”的抽象,或者执行其他操作,因此父级和子级链接只能通过导出的“方法”来修改。被证明是正确的。

我认为我想做的只是在lua中是不可能的,缺少putting _parent inside of _self (therefore making it "public"), and asking pretty please for nobody else to touch it,如果我没记错的话,那就是Python如何处理这个问题。

但是,可能有一种我没有想到的方法可以实现,也许可以使用另一种方式来抽象“类”的概念。有人知道如何在lua中实现“访问同一类的单独实例的私有成员”的抽象吗?

1 个答案:

答案 0 :(得分:1)

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)