如何在我的示例中实现 Lua 面向对象编程?

我正在尝试在Lua中创建一个类,该类保存有关该类正在关注谁的信息,并且我还希望被关注的类了解它的关注者。

但是我的代码失败了,我不知道为什么。

错误是

lua:OOP.lua:90:尝试调用方法“getName”(空值)


--------
--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())
点赞
用户1190388
用户1190388

car2正在追随(follow)car1。然而,稍后你试图访问car1的领导者,这当然会返回nil,从而导致错误。

print("车辆"..car1:getName().."的追随者是"..car1:getFollower():getName())
2014-07-31 19:26:07
用户2698261
用户2698261

问题出现在你的测试代码中,据我所见:

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

car1 没有定义领导者。(你做了 car2:follow(car1)

一些指针:

  • 您需要在创建方法中定义字段表。这暂时不适用于您的代码,但是假设您想要执行编队。您可以执行类似于 Vehicle.platoon = {}; Tank1.platoon[Tank2] = true 这样的操作 - 这将将Tank2添加到Vehicle的编队中,并与每个车辆共享。如果您在新方法中定义了这个 : function newVehicle(...) tbl.platoon = {} ... end,那么每辆车都会是唯一的。

  • 除非您有充分的理由使用它们,否则请勿使用访问器(get *,set *)方法。它们会添加杂乱,而且不利于性能。使用它们的一个好理由是如果您正在访问访问器方法中的表,并希望简化与该表的交互。 (即 Obj:addChild(Obj2) obj:hasChild(Obj2)),但然后它可能不再符合访问器的定义了:)

  • 对于未设置的字段,您可以使用虚拟对象。这将防止像你这样的错误:

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

在您的代码中,这将产生:

--------------
Mazda
Harley
-- 设置了领导者! --
Mazda的领导者是无
2014-07-31 19:34:58