2014-12-27 50 views
2

我知道Lua中的「self」與Java中的「this」類似。 「this」表示Java中的當前對象,但我知道Java是面向對象的,而Lua是基於原型的。任何人都可以解釋爲什麼下面的代碼必須使用「self.last」而不是「self」來訪問鏈表的當前節點?謝謝。 :)在Lua中的類中使用self關鍵字

list = {} 
list.__index = list 

setmetatable(list, { __call = function(_, ...) 
local t = setmetatable({length = 0}, list) 
    for _, v in ipairs{...} do t:push(v) end 
    return t 
end }) 

function list:push(t) 
    if self.last then 
    self.last._next = t 
    t._prev = self.last 
    self.last = t 
    else 
    self.first = t 
    self.last = t 
    end 
    self.length = self.length + 1 
end 
+1

儘管成員函數的語法糖命名隱含參數self,但'self'不是關鍵字,而是任何其他名稱。 – Deduplicator 2014-12-28 11:09:11

回答

1

程序中有兩種不同的對象:列表對象和節點。列表對象管理鏈接的節點的一個鏈的並具有以下字段:

listobject = { 
    length = 0, -- number of nodes managed by this list object 
    first = nil, -- reference to first node in this list; nil if list is empty 
    last = nil -- reference to last node in this list; nil if list is empty 
} 

到第一節點的參考是用於迭代和預先考慮到列表中是有用的,而last參考允許有效追加。列表對象也有一個元表,這樣就可以調用它們的方法:

listobject:push({"node1"}) 

除非你做一些有趣的事情,在push方法的self參數將始終是一個列表對象,而不是一個節點。在另一方面

節點在一個鏈到下一個和前一個節點引用:

node = { 
    _next = nil, -- might be nil if not in list or last node 
    _prev = nil, -- might be nil if not in list or first node 
    -- plus some data 
} 

所以在push方法訪問self.last檢查列表是否爲空(你可能已經檢查self.length爲),如果不是,則查找當前列表中的最後一個節點,您可以在此追加傳遞給push參數的新節點。當你這樣做時,列表對象中的last(和first)引用必須被更新,顯然。列表對象(方法體內的self)是而不是節點鏈的一部分。

+0

非常感謝,siffiejoe – 2014-12-29 14:01:59

0

self用於訪問調用列表的前一個參數。 例如,如果您撥打list({"Hello"}, {"world"}, {"my"}, {"name"}, {"is"}),則list:push將被稱爲五個次。每個參數的一個呼叫。

如果沒有最後(這是self.last)指定的參數(這是第一個參數的情況下),它將設置{"Hello"}t = {"Hello"}; t.first = t; t.last = t;(自我參照表)。

如果是第二個開始,它講述了上表({"Hello"}),下表是{"my"},告訴{"my"}上表是什麼,還設置了當前表在整個「目錄」作爲最後。請記住,list:push(t)被稱爲幾次。這意味着self.last被多次調用,但在列表實例化之後,只有一個表(最後一個參數)在self.last中,每個表都有列表中下一個或上一個表的記錄。

+1

謝謝,qaisjp – 2014-12-29 14:02:24

相關問題