couple of OO questions on this piece of code [error: attempt to index local 'self' (a number value)]

trialing the OO concepts but have two questions I’m stuck on:

QUESTION 1
* Why do the use of colon (":") in the two places below “group:endLoadingPeriod” not work, and I have to change this to “.” to work? From an OO point-of-view shouldn’t this really be a colon?
* Note the error is “function arguments expected near ‘,’” on the “performWithDelay” line

QUESTION 2
* Why do I get an error with the line “self.hitPoints = hitPoints”?
* Error is “attempt to index local ‘self’ (a number value)”

Skydiver = {}  
  
function Skydiver:new()  
 local group = display.newGroup()  
  
 -- Add Skydiver  
 local diver = display.newImage("scenes/splash/images/parachutist.png")  
 physics.addBody(diver)  
 group:insert(diver)  
  
 -- Remove Skydiving after period  
 function group:endLoadingPeriod( event ) -- QUESTION 1  
 group:removeSelf()  
 end   
 group.loadingTimer = timer.performWithDelay( 3000, group:endLoadingPeriod, 1 ) -- QUESTION 1  
  
 -- Sample Public Method  
 function group:setHitpoints(hitPoints)  
 print ("group:setHitpoints")  
 self.hitPoints = hitPoints -- QUESTION 2  
 end   
  
 return group  
end  
  
return Skydiver  

Background I’ve been following is: http://jessewarden.com/2011/10/lua-classes-and-packages-in-corona.html [import]uid: 140210 topic_id: 25121 reply_id: 325121[/import]

Kind of guessing here, but for timer.performWithDelay:

[code]timer.performWithDelay(delayms, functionName, times)

– delayms must be a number (or variable pointing at one)
– functionName must be the name of a function
– times is optional, you can ignore it unless you need more than 1)[/code]

Saying “group:dothis()” is basically another way of saying “dothis(self)” which (I think) you can’t do inside any function () space because it’s just looking for a reference. ie: dothis is the name of a function. group:dothis is not.

However since it’s basically a table, group.dothis would be a valid function name.

You can just sidestep that with a wrapper though

timer.performWithDelay(3000, function() return group:endLoadingPeriod() end )

…that should work

With regards to your second question, not sure but the tutorial you’re looking at uses group.hitPoints = hitPoints, not self.hitPoints = hitPoints, when creating the player for the first time… [import]uid: 41884 topic_id: 25121 reply_id: 102119[/import]

thanks re Q1

re Q2
* I did try setting hitPoints in the “new” so it is already set
* still get the same issue however which is:
attempt to index local ‘self’ (a number value)
* any ideas what is wrong here - I seem to be following what the OO blog suggests
* another cut of the code with the group variable name changed to skydiver is below, kind of reads better…

Skydiver = {}  
  
function Skydiver:new()  
 local skydiver = display.newGroup()  
  
 -- Add Skydiver  
 local diver = display.newImage("scenes/splash/images/parachutist.png")  
 physics.addBody(diver)  
 skydiver:insert(diver)  
  
 -- Remove Skydiving after period  
 function skydiver.endLoadingPeriod( event )  
 skydiver:removeSelf()  
 end   
 skydiver.loadingTimer = timer.performWithDelay( 3000, skydiver.endLoadingPeriod, 1 )  
  
 -- Sample Public Method  
 diver.hitPoints = 0  
 function skydiver:setHitpoints(hitPoints)  
 print ("skydiver:setHitpoints")  
 self.hitPoints = hitPoints -- \<=== \*\*\* THROWS ERROR HERE \*\*\*  
 end   
  
 return skydiver  
end  
  
return Skydiver  

And how it is called:

 local jumper = Skydiver:new()  
 jumper.setHitpoints(111)  

[import]uid: 140210 topic_id: 25121 reply_id: 102172[/import]

The : operator in Lua does some interesting things, both when declaring a function and calling it.

Declaration:

function object.doStuff(self)

is the same as

function object:doStuff()

Calling:

object.doStuff(object)

is the same as

object:doStuff()

The : operator just adds the table it’s attached to as the first parameter (named ‘self’) invisibly. When declaring, this means in your function you can use the variable self, even though it was not declared anywhere. When calling it allows you to pass in the object the function is referenced from in a way that’s easier on the eyes.

The problem you are having is that you’ve declared your function with :, so there are 2 input parameters to that function, but you are calling it with . and only 1 parameter, meaning that the number you’ve passed into that function is the first parameter, which is actually the ‘self’ variable.

The solution is either:

jumper:setHitpoints(111);  
jumper.setHitpoints(jumper, 111)  

Both those lines result in the exact same operation, but are simply 2 different ways of calling the same function. [import]uid: 134101 topic_id: 25121 reply_id: 102173[/import]

Ntero - thanks for the reponse

When I changed the calling line to “jumper:setHitpoints(111)”, but then I got:

ERROR: table expected. If this is a function call, you might have used '.' instead of ':'  

Can you see where the error is here?

[import]uid: 140210 topic_id: 25121 reply_id: 102176[/import]

Update: This seems to work re template for how to setup (a) function and (b) listener in an OO like way. In particular in the listener function don’t try to use “self”, but rather just use “event.target” to get a handle to your object instance.

Main:

Inventory = require("inventory")  
inventory = Inventory:new()  
inventory:printScore() -- Works fine (using "self")  

Class:

-- OO Class called Inventory  
Inventory = {}  
function Inventory:new()  
 local inventory = display.newGroup()  
  
 -- Class Contents: Start ---------------------  
 inventory.score = 6  
  
 local inventoryImage = display.newImage( "inventory\_button.png", 0, 0)  
 inventoryImage.y = display.contentHeight - inventoryImage.height/2  
 inventory:insert(inventoryImage)  
  
  
 function inventory:printScore()  
 print("In printScore: Score = " .. self.score)  
 end  
  
 function inventory.test\_Listener(event)  
 if (event.phase == "began") then  
 print("In test\_Listener: Score = " .. event.target.score)  
 end  
 end  
  
 inventory:addEventListener("touch", inventory.test\_Listener)  
 -- Class Contents: End ---------------------  
  
 return inventory  
end  
return Inventory  

[import]uid: 140210 topic_id: 25121 reply_id: 102469[/import]