How to access methods for instances of a class?

17 replies [Last post]
MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

Hi,

I'm just starting so I'm still trying to get a good understanding of the basics.
here is a simplified version of what I am trying to do : basically adding a number of balls to the screen and move them.
My questions are contained in the code and will be easier to understand in the context.

Any pointer is greatly appreciated :)

Code

main.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require ("Balls")
require ("Ball")
 
local Game = {}
 
function Game:startSetup()      
        local Balls = Balls:new()
        Balls:setup()
end
 
Game:startSetup()
 
Balls:animate()
 
-- How can I change the position of an instance of my Ball class?
-- I would like to move my objects (circles) independantly
-- -> ................

balls.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Balls = {}
Balls_mt = {__index = Balls}    
 
function Balls:new()
        local new_inst = {}
        setmetatable(new_inst, Balls_mt)        
        return new_inst
end
 
-- ---------------------------------------
-- SETUP
-- ---------------------------------------
function Balls:setup()
        -- Set Balls Defaults
        local params = {
                { radius=20, xdir=1, ydir=1, xspeed=2.8, yspeed=6.1, r=255, g=0, b=0, posx=400, posy=150 },
                { radius=50, xdir=-1, ydir=-1, xspeed=1.8, yspeed=1.5, r=115, g=23, b=33, posx=200, posy=200 }
        }
 
        for i, j in pairs(params) do
                ball = Ball:new(j)              
        end
 
end
 
-- ---------------------------------------
-- ANIMATE
-- ---------------------------------------
function Balls:animate()
 
        local _Balls=self
        -- Question : How to access .move method for each instance of the Ball class?
        for i, ball in pairs(_Balls) do
                ball:move() -- Doesn't work | Error : attempt to index local 'ball' (a function value)
        end
        
end
 
return Balls

ball.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Ball = {}
Ball_mt = {__index = Ball}      
 
function Ball:new(params)
 
        local new_inst = {}
        setmetatable(new_inst, Ball_mt)
        
        -- Default Location
        local default_xpos = display.contentWidth*0.5
        local default_ypos = display.contentHeight*0.5
        
        -- Draw Ball
        local new_inst = display.newCircle(default_xpos, default_ypos, params.radius )
        new_inst.x = params.posx
        new_inst.y = params.posy
        
        -- Copy params to new_inst
        for i, j in pairs(params) do
                new_inst[i] = j
        end
        return new_inst
end
 
-- I need to access that function from main.lua and balls.lua
function Ball:move()
        print ("Move Ball")
end
 
return Ball

My questions

1. I believe that if I understand how to access methods for instances of a class I will be able to make progress
2. Is there a table that stores all the instances of a class?

Thank you :)

Replies

dmekersa
User offline. Last seen 3 hours 18 min ago. Offline
Joined: 21 Jul 2011

When you call a function with ":" like ball:move() there is an hidden parameter call "self" which point to the instance. Use self.[anyproperty] to access instance properties.
Hope it helps.

MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

Thank you for the answer.
I am not sure how your suggestion is suited to my case?

1
2
3
4
5
local _Balls=self
        -- Question : How to access .move method for each instance of the Ball class?
        for i, ball in pairs(_Balls) do
                ball:move() -- Doesn't work | Error : attempt to index local 'ball' (a function value)
        end

ball.move() doesn't work either.

I want to access the method for my instances (are methods same as properties in programming?), and I believe that I already pass the instance to the move function because ball is taken from _Balls and local _Balls=self .

I can't see where I would need to modify my script and the relevancy of your answer doesn't appear clearly to my eyes.
Can you elaborate?

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

I am also finding this a little confusing, I can easily do what I want to do with a single instance of a display object e.g. ball but when I create multiple instances its becomes unclear how to access a single instance. On day day 2 of learning will check back here to hopefully get a clearer picture.

dmekersa
User offline. Last seen 3 hours 18 min ago. Offline
Joined: 21 Jul 2011

Hum, why are you using:
local _Balls=self
?

As pairs need the table containing your balls.

I'm not confortable with your sample. Here is mine:

balls.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Ball = {}
Ball_mt = {__index = Ball}      
 
-- Note the use of '.' instead of ':' because it's not a method of an instance
function Ball.new()
 
        local new_inst = {}
       --  setmetatable(new_inst, Ball_mt) -- removed!
        
        -- Default Location
        local default_xpos = display.contentWidth*0.5
        local default_ypos = display.contentHeight*0.5
        
        -- Create Display Object for Ball
        local new_inst = display.newCircle(default_xpos, default_ypos, params.radius )
        new_inst.x = params.posx
        new_inst.y = params.posy        
 
        return setmetatable(new_inst,Ball_mt)
end
 
-- I need to access that function from main.lua and balls.lua
function Ball:move(dist)
        print ("Move Ball")
        self.x = self.x + dist -- example of accessing a property
end
 
return Ball

Now how to create 2 balls and move them :

1
2
3
4
5
6
7
_balls = require("balls")
 
local ball1 = _balls.new()
local ball2 = _balls.new()
 
ball1:move(5)
ball2:move(10)

dmekersa
User offline. Last seen 3 hours 18 min ago. Offline
Joined: 21 Jul 2011

-- Edit -> I replaced
function Ball:new()
by
function Ball.new()

because new is not a class method and do not need to receive the hidden self parameter.

Read more here:
http://www.lua.org/pil/16.html

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

HAHA, much better. Thx for the insight. I found this tutorial which also has a great approach to OOP if any one needs further help.

http://www.ludicroussoftware.com/blog/2011/07/06/simple-oop-with-inheritance-in-corona/

On the way to being able to get stuck in.

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

HAHA, much better. Thx for the insight. I found this tutorial which also has a great approach to OOP if any one needs further help.

http://www.ludicroussoftware.com/blog/2011/07/06/simple-oop-with-inheritance-in-corona/

On the way to being able to get stuck in.

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

HAHA, much better. Thx for the insight. I found this tutorial which also has a great approach to OOP if any one needs further help.

http://www.ludicroussoftware.com/blog/2011/07/06/simple-oop-with-inheritance-in-corona/

On the way to being able to get stuck in.

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

Opps, it kept asking me to verify. BUG

MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

dmekersa >
Thank you very much for taking the time to answer. I appreciate.
I will take the time to study (started a few days ago and I was stuck).

I have a question :
In your example each ball is manually created
local ball1 = _balls.new()

How would you create a function so that you can populate Balls (10 at once for example) and still access each instance easily later?
Would you store the names in a table or, what would be the best practice?

Beloudest
User offline. Last seen 1 week 5 hours ago. Offline
Joined: 15 Jan 2012

Me too, same question. Does not seem intuitive to manually declare each ball?

dmekersa
User offline. Last seen 3 hours 18 min ago. Offline
Joined: 21 Jul 2011

In a table, using table.insert then browsing the table with pairs, example :

1
2
3
for k in pairs(listBall) do
     listBall[k]:move()
end

read http://lua-users.org/wiki/TablesTutorial

MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

dmekersa
Thank you. I have read the docs at lua-users (and more) but I guess I will learn more with time.

I have a last question : I can't access methods on my instances of Ball after I have stored them in a table, but I can access some of their properties.
-> attempt to call method 'move' (a nil value)

Where am I mistaking?

If someone could point me in the right direction, that would be great.
Thank you!

Code

main.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
_balls = require ("Balls")
_ball = require ("Ball")
require ("libraries")
 
local Game = {}
 
 
function Game:startSetup()      
        local Balls = _balls.new()      
        local listBalls = _balls:setup()        
        
        print (listBalls[1].x) -- Displays "400", great until there
 
        listBalls[1]:move(50) -- Doesn't work.How can I access function move() in ball.lua
end
 
Game:startSetup()

balls.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Balls = {}
Balls_mt = {__index = Balls}    
 
local listBalls = {}
 
function Balls.new()
        local new_inst = {}
        setmetatable(new_inst, Balls_mt)        
        return (new_inst)
end
 
 
-- ---------------------------------------
-- SETUP
-- ---------------------------------------
function Balls:setup()
        -- Set Balls Defaults
        local params = {
                { radius=20, xdir=1, ydir=1, xspeed=2.8, yspeed=6.1, r=255, g=0, b=0, posx=400, posy=150 },
                { radius=50, xdir=-1, ydir=-1, xspeed=1.8, yspeed=1.5, r=115, g=23, b=33, posx=200, posy=200},
                { radius=20, xdir=1, ydir=1, xspeed=2.8, yspeed=6.1, r=255, g=0, b=0, posx=400, posy=350 }
        }
 
        for i, j in pairs(params) do
                local ball = _ball.new(j)       
                table.insert(listBalls, ball)
                ball = nil
        end
 
        return (listBalls)
        
end
 
return Balls

ball.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Ball = {}
Ball_mt = {__index = Ball}      
 
function Ball.new(params)
 
        local new_inst = {}
       setmetatable(new_inst, Ball_mt)
 
                
        -- Default Location
        local default_xpos = display.contentWidth*0.5
        local default_ypos = display.contentHeight*0.5
        
        -- Create Display Object for Ball
        new_inst = display.newCircle(default_xpos, default_ypos, params.radius )
        new_inst.x = params.posx
        new_inst.y = params.posy        
 
        return (new_inst)
end
 
function Ball:move(dist)
        print ("Move Ball")
        --self.x = self.x + dist -- example of accessing a property
end
 
return Ball

Note

On top of my previous question here is another one :

When I use
return setmetatable(new_inst,Ball_mt)
I can access my "move" method but print (listBalls[1].x) gives me a nil

On the other hand :
return (new_inst)
I can't access my "move" method but print (listBalls[1].x) gives me 400 (correct value)
attempt to call method 'move' (a nil value)> I would like to store access .x and other properties on my ball objects AND access the method from the class move().
How would I achieve that?

Also in the docs Lua Simple classes setmetatable is not done on return.

Can somebody explain me what I should learn from that difference?
Thank you!

MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

If anyone could please take a look at my last message above, it probably shouldn't take more than 2 minutes for someone a bit experienced.
This guy on the picture is worried that I will never be able to start working on my platformer.
Help him, help me.

Thank you

jeremyapplebaum12
User offline. Last seen 3 weeks 4 days ago. Offline
Joined: 20 Jan 2011

Do you have a copy of require libraries.lua?

Thanks.

MrMells
User offline. Last seen 1 year 50 weeks ago. Offline
Joined: 4 Oct 2011

Hi Jeremy,

in fact libraries.lua is nothing special, just my own lua file for testing purposes.

jeremyapplebaum12
User offline. Last seen 3 weeks 4 days ago. Offline
Joined: 20 Jan 2011

Try this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Ball = {}
Ball_mt = {__index = Ball}      
 
function Ball.new(params)
 
        local new_inst = {}
 
                
        -- Default Location
        local default_xpos = display.contentWidth*0.5
        local default_ypos = display.contentHeight*0.5
        
        -- Create Display Object for Ball
        new_inst = display.newCircle(default_xpos, default_ypos, params.radius )
        new_inst.x = params.posx
        new_inst.y = params.posy        
        setmetatable(new_inst, Ball_mt)
        return (new_inst)
end
 
function Ball:move(dist)
        print ("Move Ball")
        --self.x = self.x + dist -- example of accessing a property
end
 
return Ball

Viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.