【发布时间】:2013-12-31 16:47:42
【问题描述】:
我正在尝试在 lua 中创建类。我编写了一些简单的代码来设置和获取字符串值,但结果我一直返回 null。
这是我的类定义的样子:
appUser = {}
appUser_mt = { __index = appUser }
-- This function creates a new instance of appUser
function appUser:new()
local new_inst = {} -- the new instance
setmetatable( new_inst, appUser_mt)-- all instances share the same metatable.
return new_inst
end
-- Here are some functions (methods) for appUser:
function appUser:setLastName(lname)
appUser._lname = lname
end
function appUser:setFirstName(fname)
appUser._fname = fname
end
function appUser:getLastName()
return appUser._lname
end
function appUser:getFirstName()
return appUser._fname
end
return appUser -- do I need this???
我尝试创建 2 个用户的测试代码如下所示:
require "user"
local a = appUser:new{setLastName="Doe"}
local b = appUser:new{setLastName="Doe-Doe"}
print(a.getLastName())
print(b.getLastName())
当我从命令行运行测试脚本时,这是我得到的:
mydevbox:/usr/share/vsx/lib/testapp# lua testuser.lua
nil
nil
mydevbox:/usr/share/vsx/lib/testapp#
到目前为止我所做的尝试:
我尝试改变调用方法的方式 打印(a.getLastName()) 到 打印(a:getLastName())
-
我已将变量定义更改为:
appUser._lname 到 _lname
让我的代码看起来像这样:
local _lname
function appUser:setLastName(lname)
_lname = lname
end
function appUser:getLastName()
return _lname
end
我不确定我做错了什么。任何建议,将不胜感激。 谢谢。
编辑 1
对代码进行了以下更改以测试 Etan 的答案和我的答案: 1.我已将构造函数更改为接受我的答案中所述的参数... 2. 我在 set/get 函数的主体中添加了对“self”的引用。
-- This function creates a new instance of appUser
appUser = {}
appUser_mt = { __index = appUser }
function appUser:new(new_inst)
new_inst = new_inst or {} -- the new instance
setmetatable( new_inst, appUser_mt)-- all instances share the same metatable.
return new_inst
end
-- Here are some functions (methods) for appUser:
function appUser:setLastName(lname)
self._lname = lname
end
function appUser:setFirstName(fname)
self._fname = fname
end
function appUser:getLastName()
return self._lname
end
function appUser:getFirstName()
return self._fname
end
测试脚本中的对象 A 和 B 仍然以 nil 失败,但 C 有效,因为我创建它的方式与实例化 a 或 b 不同。 (请看我的回答)
编辑 2
appUser = {}
appUser_mt = { __index = appUser }
function appUser:new()
return setmetatable( {}, appUser_mt)-- all instances share the same metatable.
end
local function validate_vmail(vmail_id)
local success = true
if type(vmail_id) ~= 'string' then
success = false
end
if not exists_in_database(vmail_id) then
success = false
end
return success
end
function appUser_mt.__index(t, k)
if k == 'lastName' then
return t._lastName
end
return rawget(t, k)
end
function appUser_mt.__newindex(t, k, v)
local success = false
if k == 'lastName' then
k = '_lastName'
v = v:gsub('^.', string.upper) -- Make sure the first letter is uppercase.
success = true
end
if k == 'vmail_id' then
if validate_vmail(v) then
v = v
success = true
else
success = false
end
end
if success then
rawset(t, k, v)
end
end
return appUser
这是实例化这个类的客户端:
local a = appUser:new()
a.lastName = "doe"
print(a.lastName)
local b = appUser:new()
b.lastName = "dylan"
print(b.lastName)
a.vmail_id = 1234
print(a.vmail_id)
代码似乎可以正常工作,但我想确保到目前为止我理解了您的 cmets / 答案。
【问题讨论】:
-
a 和 b 仍然不起作用,因为您需要使用
appUser:new{_lname="Doe"}而不是appUser:new{setLastName="Doe"}。您需要预定义您的方法分配的字段,而不是使用您的方法名称预定义字段。 -
Etan,顺便说一句,感谢您提供的所有帮助。我理解您关于设置字段而不是方法的评论。但从技术上讲,在进行 OOP 时,客户不应该知道我的类中使用的内部变量的名称......这就是为什么我想提供公共方法来访问和更改值的原因。这有意义吗?
-
是的,我明白你为什么要这么做。我的意思是你不能按照你写的东西去做。如果您愿意,您可以在新函数表参数中从方法名称转换为字段名称(或更好的方法调用),但这不是您编写的代码。