Using self keyword in a class in Lua
I know that "me" in Lua is like "this" in Java. "this" means the current object in Java, but I know Java is object-oriented and Lua is prototype. Can anyone explain why the below code should use "self.last" instead of "self" to access the current node of the linked list? Thank.:)
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
source to share
There are two different types of objects in your program: list of objects and nodes. The list object manages a chain of related nodes and has the following fields:
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
}
The link to the first node is useful for iterating and adding to the list, and the link last
allows you to add efficiently. List objects also have a meta tag so you can call them with methods:
listobject:push( {"node1"} )
Unless you do something funny, the self
method parameter push
will always be a list object, not a node.
Nodes, on the other hand, have links to the next and previous node in the chain:
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
}
So, in the method, push
you access to self.last
check if it is empty (you might as well check self.length
), and if not, find the last node in the current list to which you can add a new node passed as an argument push
. When you've done that, the links last
(s first
) in the list object should be updated, obviously. The list object ( self
in the body of the method push
) is not part of the chain of nodes.
source to share
self
used to access the previous argument being called into the list. For example, if you called list({"Hello"}, {"world"}, {"my"}, {"name"}, {"is"})
, you list:push
would get the name five . One call for each argument.
If no last (this self.last
) argument is specified (this refers to the first argument), it will set {"Hello"}
to t = {"Hello"}; t.first = t; t.last = t;
(self referring tables).
If it is second and onwards, it tells the previous table ( {"Hello"}
) that the next table is {"my"}
, reports {"my"}
what the previous table is, and also sets the current table in the entire "list" as the last one. Be aware that this list:push(t)
is called multiple times. This means that self.last is called many times, but after the list has been created, only one table (the last argument) is in self.last
, and each table has an entry for the next or previous table in the list.
source to share