-1

I'm trying to do some OOP in Lua (newcomer), and I've come to this problem. I think it may have something to do with pointers although I can't seem to wrap my mind around it.

This is the code:

Atom = {
    px = 0,
    py = 0,
    vx = 0,
    vy = 0,
    r = 255,
    g = 255,
    b = 255
}

function Atom:new ( pos_x, pos_y, r_t, g_t, b_t )
    local atom = {}
    setmetatable(atom, self)
    self.__index = self
    self.px = pos_x or 0
    self.py = pos_y or 0
    self.vx = 0
    self.vy = 0
    self.r = r_t or 255
    self.g = g_t or 255
    self.b = b_t or 255
    return atom
end


Running the following script I get some wacky results:

math.randomseed(os.time())

a = {} -- Can't be local
for i=1,5 do
    a[i] = Atom:new(math.random())
end

for i=1,5 do 
    print(a[i])
    print(a[i].px)
end
table: 0000000000799590
0.56619703258596
table: 00000000007994d0
0.56619703258596
table: 00000000007991d0
0.56619703258596
table: 00000000007996d0
0.56619703258596
table: 00000000007995d0
0.56619703258596

As you can see, the referenced tables are different but the numeric value of the variables are the same.

What am I doing wrong?

I apologise if there's something obviously wrong, as previously said, I'm a newcomer :-)

  • Does this answer your question? [Lua objects not unique](https://stackoverflow.com/questions/40010249/lua-objects-not-unique) – Nifim Mar 11 '23 at 00:24

2 Answers2

2

In function Atom:new the variable self refers to Atom so you are writing the variable Atom.px 5 times.

Because of the metatable thing, when you look at px inside any atom table, and Lua doesn't find it, it looks at Atom as well and it does find a px variable there.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • 1
    Side note: `self` only refers to `Atom` since the function is also called as `Atom:new` (and not due to the function "declaration"); if it were called as `Atom.new({}, ...)`, `self` would be a new object. – Luatic Mar 11 '23 at 09:04
1

Try this code:

-- define the Atom class
Atom = {
    px = 0,
    py = 0,
    vx = 0,
    vy = 0,
    r = 255,
    g = 255,
    b = 255
}

function Atom:new(pos_x, pos_y, r_t, g_t, b_t)
    local atom = {}
    setmetatable(atom, self)
    self.__index = self
    atom.px = pos_x or 0
    atom.py = pos_y or 0
    atom.vx = 0
    atom.vy = 0
    atom.r = r_t or 255
    atom.g = g_t or 255
    atom.b = b_t or 255
    return atom
end

-- set random seed for generating random numbers
math.randomseed(os.time())

-- create 5 instances of Atom with random positions and colors
local a = {}
for i = 1, 5 do
    a[i] = Atom:new(math.random(), math.random(), math.random(255), math.random(255), math.random(255))
end

-- print the positions of the atoms
for i = 1, 5 do 
    print("Atom #"..i.." Position: ("..a[i].px..","..a[i].py..")")
end
Mike
  • 114
  • 3