2016-08-04 62 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)並插入新的方法。

相關問題