Xentai
Xentai

Reputation: 69

How to implement Lua OOP in my example?

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())

Upvotes: 1

Views: 147

Answers (2)

Advert
Advert

Reputation: 653

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

Upvotes: 2

hjpotter92
hjpotter92

Reputation: 80629

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() )

Upvotes: 1

Related Questions