How to access methods for instances of a class?

17 replies [Last post]
MrMells
User offline. Last seen 2 years 28 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 1 week 4 days 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 2 years 28 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 23 hours 56 min 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 1 week 4 days 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 1 week 4 days 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 23 hours 56 min 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 23 hours 56 min 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 23 hours 56 min 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 23 hours 56 min ago. Offline
Joined: 15 Jan 2012

Opps, it kept asking me to verify. BUG

MrMells
User offline. Last seen 2 years 28 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 23 hours 56 min ago. Offline
Joined: 15 Jan 2012

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

dmekersa
User offline. Last seen 1 week 4 days 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 2 years 28 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 2 years 28 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 10 weeks 6 days ago. Offline
Joined: 20 Jan 2011

Do you have a copy of require libraries.lua?

Thanks.

MrMells
User offline. Last seen 2 years 28 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 10 weeks 6 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.