Lua函数中传递对象总是引用self
我正在尝试在Lua中创建一个对象("room"),它具有一个函数来检查其他提供的房间是否与它相交。
我遇到的问题是,无论传递什么参数,它似乎总是与我在函数调用的对象相同。
Room = {
Width = 0,
Height = 0,
X = 0,
Left = 0,
Right = 0,
Top = 0,
Bottom = 0
}
function Room:new(width, height, x, y)
self.Width = width
self.Height = height
self.X = x
self.Y = y
self.Left = x
self.Right = self.X + self.Width
self.Top = y
self.Bottom = self.Y + self.Height
return self
end
function Room:Intersects(other)
print("Checking for intersection...")
print("Self X: ", self.X)
print("Self Y: ", self.Y)
print("Other X: ", other.X)
print("Other Y: ", other.Y)
return other.Left < self.Right and self.Left < other.Right and other.Top < self.Bottom and self.Top < other.Bottom
end
room1 = Room:new(5, 6, 3, 3)
room2 = Room:new(10, 16, 5, 9)
intersects = room1:Intersects(room2)
print("Intersects: ", intersects)
输出:
$ lua FunctionTest.lua
Checking for intersection...
Self X: 5
Self Y: 9
Other X: 5
Other Y: 9
Intersects: true
我希望self.X,self.Y与other.X和other.Y不同。我一直在遵循Lua.org的面向对象编程 章节。
如Dahk所说,您定义的Room表也是您返回的“new”Room对象。
“Room:方法(... )”是“Room.method(Room,...)”的语法简写。
Lua提供的“self”变量在使用简写时包含对Room的引用,因此当您键入“Room:new(5、6、3、3)”时,Lua读取的是“Room.new(Room,5、6、3、3)”,其中'self = Room'。然后我们让“self.width = 5”发生的是“Room.width = 5”,这不是我们想要发生的。
为了解决这个问题,每次调用“Room:new”时我们需要创建一个新对象。我们创建一个称为obj的新表,然后在其中存储这些值。
function Room:new(width, height, x, y)
local obj = {
Width = width,
Height = height,
X = x,
Y = y,
Left = x,
Right = x + width,
Top = y,
Bottom = y + height,
}
return obj
end
这很有效,我们现在可以创建房间。但是,当我们尝试执行“room1:Intersects(other)”时,我们会收到一个错误:“方法Intersects未定义”。我们可能已经定义了一个新的房间,但这个房间不过是一个简单的表。这就是元表的作用。简而言之,元表定义了表的行为。在我们的情况下,我们希望它包含Lua在原始列表中找不到值或方法时查找的内容。 (有关元表的更多信息,请参见第13章。)
让我们看一个例子:
如果每个房间的地板都相同,我们可以将该地板复制到每个子级中,或者我们让“Room.floor =“ Carpet””,并在有人问我们某个房间的地板时返回该房间。为了返回这个值,我们使用元表和__index方法。这种方法是Lua查找找不到的值的地方。
function Room:new(width, height, x, y)
local obj = {
...
}
setmetatable(obj, self) -- 这里的self等于Room
self.__index = self
return obj
end
同样,我们创建了具有单独存储每个房间所需的所有值的对象。然后,我们让Room成为obj的元表。第三行告诉我们,在找不到任何方法时应使用Room表。
在创建对象时使用self.__index = self的使用方式与在定义Room本身时写入Room.__index = Room相同,但在每次复制相同/类似代码时会有所帮助 :)
如果我们定义了Room.floor =“ Carpet”,则print(room1.floor)的结果将是所预期的Carpet。room1.floor的值为nil,然后Lua将在room1的元表中查找__index,在那里它发现Room可能包含它正在寻找的内容。确实,Room.floor已定义,因此这是Lua作为答案看到的内容。
总结
您还可以设置元表并使用__index方法定义所需的对象。我认为它可能还更具有内存效率,因为您不必为相同类的每个对象单独定义每个函数。
另外,如果您希望Room:Intersects在执行类似于room1:intersects(room1)之类的操作时返回false,则只需添加self〜= other。仅当self和other是完全相同的表格时才会成功,即使房间的所有值都相同,它们也不会相等,并相互相交。
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

Room是在顶部定义的单个表格,所有对Room的引用都是作用于同一个表格而不是不同的对象。下面的解决方案创建了一个名为'obj'的不同表格,并在每次调用
NewRoom()时返回此唯一的表格。这种方法与您引用的指南的第16.4章类似。function NewRoom(width, height, x, y) local obj = { Width = width, Height = height, X = x, Y = y, Left = x, Right = x + width, Top = y, Bottom = y + height, } function obj:Intersects(other) print("Checking for intersection...") print("Self X: ", self.X) print("Self Y: ", self.Y) print("Other X: ", other.X) print("Other Y: ", other.Y) return other.Left < self.Right and self.Left < other.Right and other.Top < self.Bottom and self.Top < other.Bottom end return obj end room1 = NewRoom(5, 6, 3, 3) room2 = NewRoom(10, 16, 5, 9) intersects = room1:Intersects(room2) print("Intersects: ", intersects)