1

I am trying to create a class in Lua, which holds information about who is this class following, and I also want followed class to know about his follower.

But my code fails, and I dont know why.

The error is

lua: OOP.lua:90: attempt to call method 'getName' (a nil value)

Vehicle = {}

--------
--FIELDS
--------
Vehicle.name = ""
Vehicle.vtype = "";
Vehicle.follower = {};
Vehicle.leader = {};

---------------------
--SETTERS AND GETTERS
---------------------

function Vehicle:setName(value)
    self.name = value
end
function Vehicle:getName()
    return self.name
end

function Vehicle:setType(value)
    self.vtype = value
end

function Vehicle:getType()
    return self.vtype
end

function Vehicle:setFollower(pVeh)
    self.follower = {};
    self.follower = pVeh;
end;

function Vehicle:getFollower()
    return self.follower;
end;

function Vehicle:getLeader()
    return self.leader;
end;

function Vehicle:setLeader(pVeh)
    self.leader = pVeh;
    if (self.leader ~= nil) then
        print ("-- setted leader! --");
    end;
end;

-----------
--METHODS--
-----------

function Vehicle:follow(pVeh)  --> why does this not work?
    self:setLeader(pVeh);
    pVeh:setFollower(self);
end;


-- constructor
function newVehicle(pNm,pTp)
    tbl = {}
    setmetatable(tbl, {__index = Vehicle});
    tbl:setName(pNm);
    tbl:setType(pTp);
    return tbl
end
-----------------------------------------------
-- TEST
-----------------------------------------------
local car1 = newVehicle("Mazda","Car");
local car2 = newVehicle("Harley","Bike");
print("--------------");
print (car1:getName()); --> prints "Mazda"
print (car2:getName()); --> prints "Harley"
car2:follow(car1)
print ("Leader of " .. car1:getName() .. " is " .. car1:getLeader():getName())
0

2 Answers 2

2

The problem is in your test code, from what I can see:

print ("Leader of " .. car1:getName() .. " is " .. car1:getLeader():getName())

car1 does not have a leader defined. (you did car2:follow(car1))

Some pointers:

  • You need to define field tables in the creation method. This won't apply to your code just yet, but say you wanted to do platoons. You'd do something like Vehicle.platoon = {}; Tank1.platoon[Tank2] = true -- This would add Tank2 to Vehicle's platoon table, and share it with every vehicle. If you define this in the new method: function newVehicle(...) tbl.platoon = {} ... end, then it would be unique to every vehicle.

  • Don't use accessor (get*, set*) methods unless you have a solid reason for using them. They add clutter, and are not good for performance. A good reason to use them would be if you are accessing a table in your accessor method, and want to simplify the interaction with that. (i.e Obj:addChild(Obj2) obj:hasChild(Obj2)) But then it probably doesn't qualify as an accessor anymore :)

  • You can use dummy objects for unset fields. This'll prevent errors like yours:

    local Dummy = newVehicle("None", "None")
    Vehicle.follower = Dummy
    Vehicle.leader = Dummy
    

In your code, this produces:

--------------
Mazda
Harley
-- setted leader! --
Leader of Mazda is None
Sign up to request clarification or add additional context in comments.

1 Comment

The error distracted you, it's happened to me before. Be very careful with tables in your __index, too, since they are references :)
1
car2:follow(car1)

car1 is being followed by car2. Whereas, later; you're trying to access car1's leader, which, of course returns nil. Hence the error.

print( "Follower of "..car1:getName().." is "..car1:getFollower():getName() )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.