gpt4 book ai didi

class - lua 类 - 无法设置属性和检索值

转载 作者:行者123 更新时间:2023-12-01 12:45:09 25 4
gpt4 key购买 nike

我正在尝试在 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#

到目前为止我尝试了什么:

  1. 我试过改变调用方法的方式 打印(a.getLastName())至 打印(a:getLastName())

  2. 我更改了以下变量定义:

    appUser._lname至 _lname

所以我的代码看起来像这样:

local _lname
function appUser:setLastName(lname)
_lname = lname
end

function appUser:getLastName()
return _lname
end

我不确定我做错了什么。任何建议,将不胜感激。谢谢。

编辑 1

为了测试 Etan 的答案和我的答案,对代码进行了以下更改:1. 我已将构造函数更改为接受我的回答中所述的参数...2. 我在设置/获取函数的主体中添加了对“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)

代码似乎可以正常工作,但我想确保到目前为止我理解了您的评论/回答。

最佳答案

模块

您没有在任何地方分配 require "user" 的结果,所以我假设您可能在某处隐藏了一个 module 调用。如果您打算在不调用 module 的情况下使用它,则需要 return appUser,例如:

-- mlib.lua
local M = {}
function M.add(a, b) return a + b end
return M

-- script.lua
local m = require'mlib'
print(m.add(2, 2))

构造函数

您可以简化构造函数。

function appUser.new()
return setmetatable({}, appUser_mt)
end

我想我理解您对以下代码的意图,但如果不进行一些调整,它就不会按照您希望的方式工作。我会回到这个问题上。

local a = appUser:new{setLastName="Doe"}
local b = appUser:new{setLastName="Doe-Doe"}

函数

请记住,无论何时使用 : 定义函数,您都在插入隐式 self 参数作为第一个参数。调用函数也是如此。

function t:f() end
function t.f(self) end
t.f = function(self) end

所有这些行都是等价的语句。

t['f'](t)
t.f(t)
t:f()

二传手/吸气手

Setter 和 getter 不在任何需要的地方,因为情况可能在其他语言中。在 Lua 中没有表的私有(private)或公共(public)接口(interface)的概念,所以如果你所做的只是分配和检索,你当前的设置可能会成为 future 的维护责任。执行以下操作没有错。

local class = {}
class.lastName = 'Doe'

事实上,有元方法设施,如果您确实想要 setter 但又希望它们融入 具有其他属性。让我举个例子。

local mt = {}
function mt.__index(t, k)
if k == 'lastName' then
return t._lastName
end
end

function mt.__newindex(t, k, v)
if k == 'lastName' then
k = '_lastName'
v = v:gsub('^.', string.upper) -- Make sure the first letter is uppercase.
end

rawset(t, k, v)
end

local class = setmetatable({}, mt)
class.lastName = 'smith'
print(class.lastName) -- Smith

构造函数,pt。 2

为了稍微分解一下,让我们看一下下面的语句。

local a = appUser:new{setLastName="Doe"}

{setLastName = "Doe"} 部分只是用名为 setLastName 的键(或属性)构造一个表,其值为"Doe",它们都是字符串。然后将其用作appUsernew 函数的第二个 参数。 appUser 是第一个参数,用作前面提到的隐式 self 参数。记住 :

其实完全没有必要。将 appUser.new 调用和定义为一个没有 self 的函数就足够了,因为它不需要。仅此而已。 new 在任何方面都不是特殊的,它会以某种方式知道 使用参数 "Doe" 调用 setLastName ,但我们可以那样做。


综上所述,这里有一个关于如何让构造函数按您想要的方式工作的想法。

function appUser.new(options)
return setmetatable(options or {}, appUser_mt)
end

local a = appUser.new{_lname = 'Doe'}
local b = appUser.new{_lname = 'Doe-Doe'}

但是,如果您真的想在构造函数表本身中调用函数,则需要多一点。

function appUser.new(options)
local o = setmetatable({}, appUser_mt)

for k, v in pairs(options)
-- This will iterate through all the keys in options, using them as
-- function names to call on the class with the values
-- as the second argument.
o[k](o, v)
end

return o
end

local a = appUser.new{setLastName = 'Doe'}
local b = appUser.new{setLastName = 'Doe-Doe'}

如果这还没有尽可能完整地回答您的问题,请告诉我。

关于class - lua 类 - 无法设置属性和检索值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20860549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com