2016-08-04 63 views
2

考虑下面的代码:如何在Lua对象中创建一个类表成员?

#!/usr/bin/lua 

local field = 
{ 
    name = '', 
    array = {}, 

    new = function(self, o) 
     o = o or {} 
     setmetatable(o, self) 
     self.__index = self 
     return o 
    end, 
} 

local fld1 = field:new() 
local fld2 = field:new() 

fld1.name = 'hello' 
table.insert(fld1.array, 1) 
table.insert(fld1.array, 2) 
table.insert(fld1.array, 3) 

fld2.name = 'me' 
table.insert(fld2.array, 4) 
table.insert(fld2.array, 5) 

print('fld1: name='..fld1.name..' len='..#fld1.array) 
print('fld2: name='..fld2.name..' len='..#fld2.array) 

执行时的输出如下所示:

fld1: name=hello len=5 
fld2: name=me len=5 

从输出中,可以看出的是name具有fld1fld2不同的值。然而,arrayfld1fld2fld1.arrayfld2.array是相同的,因此具有相同的长度5)具有相同的值。

如何修复此代码,使fld1.array独立于fld2.array(以便修改fld1.array不会改变fld2.array)?

回答

1

首先,fld1fld2具有不同的名称,因为你给了它们不同的名称 - 它们自己的属性

执行表键分配时,新键和值将直接存储在您指定的表中。 __index metamethod只在进行表格键查找时发挥作用,并且在表中找不到关键字。

一个快速的例子,我们可以看到表键分配shadow__index查找链中的键。

local Foo = { shared = 'shared', private = 'private' } 
Foo.__index = Foo 

local foo = setmetatable({}, Foo) 

foo.private = 'a shadowed value' 

print(Foo.shared, foo.shared) -- shared shared 
print(Foo.private, foo.private) -- private a shadowed value 

注:有一个__newindex元方法用来捕获涉及从未见过,密钥表密钥分配。

考虑治疗方法new更像是一个传统的构造函数,其中分配“私人”性质的新创建实例

local Field = { 
    -- shared properties go here 
} 

-- shared methods are defined as such 

function Field:new (name) 
    local o = { 
     -- private properties for the newly created object go here 
     name = name or '', 
     array = {} 
    } 

    self.__index = self 

    return setmetatable(o, self) 
end 

function Field:insert (value) 
    table.insert(self.array, value) 
end 

local fld1 = Field:new('hello') 
local fld2 = Field:new('me') 

fld1:insert(1) 
fld1:insert(2) 
fld1:insert(3) 

fld2:insert(4) 
fld2:insert(5) 

print('fld1: name='..fld1.name..' len='..#fld1.array) -- fld1: name=hello len=3 
print('fld2: name='..fld2.name..' len='..#fld2.array) -- fld2: name=me len=2 

一些更多的注意事项:

  • 一般情况下, '类' 的名字应该在PascalCase,使他们不同。
  • 在查找链中具有:new函数意味着实例可以调用它,但这可能是也可能不是所希望的。 (可以通过这种方式创建稍微丑陋的继承。)
  • 您如何定义使用隐式self的方法是有区别的。你应该给Chapter 16 of Programming in Lua一个阅读。如果你使用5.2或5.3,可能会过时,但它应该仍然有很多有用的信息。
  • 如果你对这个小图书馆感兴趣,我最近写了Base。如果你环顾四周,你会发现很多小的OOP包让这些事情变得更容易一些。
-1

Lua的空中接力TECHNIC不相同的C++,JAVA

__index元方法的参考目标表的记录。

等等,fld1,fld2数组项是Field的数组项。

您必须创建一个新表并使用它。

为什么名称的价值不同。因为,你的分配使用新的方法代码修复的名称

fld1.name = '你好'

简单代码修复

fld1.array = {} 

local o1 = {name = '', array = {}} 
local o2 = {name = '', array = {}} 

local fld1 = field:new(o1) 
local fld2 = field:new(o2) 

做出新的表(make o)并插入新的方法。

相关问题