Reputation: 7
I understand how to stack functions when creating a new table from the beginning like so :
Test:newNumber(5):add5():add5() --create a Number{} with Number.Num=5 then add to self.num
but im having trouble passing in previously existing tables as so:
function EnemyBase:isStandingOver( Object )
local o = Object
for k , v in pairs(Creature_Bases) do
if (o.x and o.y are over v.x and v.y) then
setmetatable( Creature_Bases[k] , self )
self.__index = self
return Creature_Bases[k]
end
end
end
function EnemyBase:changeSprite()
self.Sprite = self.SpriteTest
end
function ManageEnemies()
for k,v in pairs(Enemies) do
if EnemyBase:isStandingOver( Enemies[k] ) ~= nil then
EnemyBase:isStandingOver( Enemies[k] ):changeSprite()
end
end
end
I know ill need to create a meta method table with the __index pointing to self at some point but i don't know when.
Upvotes: 0
Views: 1241
Reputation: 28950
Let's first understand what self
is.
function a:b() end
is syntactic sugar for function a.b(self) end
A function defined like that has a parameter self
.
Function call a:b()
is syntactic sugar for a.b(a)
A function called like that always has a
as its first argument which inside the function ends up as parameter self
.
So if you have defined a function like that, you have a very simple way to access table a
through self
from within that function without explicitly using reference a
. This comes in handy if you want to do OOP in Lua.
Then we have to understand what the __index metamethod is.
__index: The indexing access operation table[key]. This event happens when table is not a table or when key is not present in table. The metavalue is looked up in the metatable of table.
The metavalue for this event can be either a function, a table, or any value with an __index metavalue. If it is a function, it is called with table and key as arguments, and the result of the call (adjusted to one value) is the result of the operation. Otherwise, the final result is the result of indexing this metavalue with key. This indexing is regular, not raw, and therefore can trigger another __index metavalue.
Let's use both of it in a simple constructor:
MyClass = {}
function MyClass:New(name)
local instance = setmetatable({}, self)
self.__index = self
instance.name = name
return instance
end
function MyClass:SayName()
print("my name is " .. self.name)
end
If we now do this:
local myFirstInstance = MyClass:New("John")
local mySecondInstance = MyClass:New("Bob")
myFirstInstance:SayName()
mySecondInstance:SayName()
what's going to happen?
We know MyClass:New()
is equivalent to MyClass.New(MyClass)
. So in our contructor self
refers to MyClass
.
local instance = setmetatable({}, self)
creates a new table and sets self
which is MyClass
as its metatable.
self.__index = self
set's MyClass
as the __index metavalue of itself.
The name
is stored in each instance and the instance is returned.
Now if you call myFirstInstance:SayName()
, Lua will look up myFirstIntance["SayName"]
. It won't find anything. So it will check wether table myFirstInstance
has a metatable and if so, if there is a __index metavalue. There is. getmetatable(myFirstInstance).__index is MyClass
so it will now actually call MyClass.SayName(myFirstInstance)
. So in the end, both instances will print their own name even though they do not even implement a SayName function. And MyClass.SayName
prints both instances names without knowing even knowing the instances or even their names.
Upvotes: 2