我在 lua 中创建程序,我创建了一个存储 3 个值的类和一个可以返回“x”值的函数。这是代码:
Vector3 = {}
Vector3.__index = Vector3
function Vector3:new(x,y,z)
local instance =
{
x = x or 0,
y = y or 0,
z = z or 0
}
setmetatable(instance, Vector3)
return instance
end
function Vector3:printX()
return self.x
end
这是我的 main.lua 代码:
require "Vector3"
vec1 = Vector3.new(1,2,3)
vec2 = Vector3.new(5,1,0)
print(vec1:printX())
这就是这条线的作用
vec1 = Vector3.new(1,2,3)
是创建一个新类并将 1 分配给 x,2 分配给 y,3 分配给 z。但是当我打印出 printX() 返回的值时,它会给我 2。如果我将它更改为打印出 y 值,它会给我 3。如果我将其更改为打印出 z 值,则它为零。我的代码有什么问题吗?
我希望它返回正确的值。
正如 tehtmi 所指出的,
function Vector3:new(x,y,z)
等同于 function Vector3.new(self,x,y,z)
。调用Vector3.new(1,2,3)
因此设置了self = 1
、x = 2
、y = 3
和z = nil
; 2
被打印出来。
有两种方法可以解决这个问题:
Vector3.new
,删除self
参数。Vector3:new
,通过self = Vector3
。这废弃了构造函数中的 Vector3
全局变量访问; setmetatable(instance, Vector3)
然后可以替换为 setmetatable(instance, self)
.如果稍微重写构造函数,您将获得《Programming in Lua》一书中概述的标准“类”模板:
function Vector3:new(x,y,z)
local instance =
{
x = x or 0,
y = y or 0,
z = z or 0
}
setmetatable(instance, self)
self.__index = self -- note the addition of this line
return instance
end
然后您可以删除
Vector3.__index = Vector3
行,因为这将在每次调用 Vector3:new(...)
时在构造函数中完成(在性能方面可以说是有问题的)。这种方法的优点是它如何处理继承:继承被简单地实现为实例化;您无需负责编写新的构造函数。假设你想要一个 Scale
类来扩展你的 Vector3
类:
Scale = Vector3:new() -- a scale is a vector ("inherits")
function Scale:scale(vec) -- scale a vector (componentwise multiplication)
return Vector3:new(self.x * vec.x, self.y * vec.y, self.z * vec.z)
end
用法:
-- Instantiation:
-- This wouldn't work if you used `.`
-- since then `Scale.new` would be just `Vector3.new`
-- which sets `Vector3` and not `Scale` as the metatable,
-- but since the `:` passes `Scale`/`Vector3` as `self`, everything is fine.
local s = Scale:new(1, 2, 3)
local v = s:scale(Vector3.new(4, 5, 6))
print(v.x, v.y, v.z) -- 4, 10, 18
你最终必须决定你是更喜欢构造函数通过上值或全局变量查找他们的类,还是让它作为
self
参数传递。
根据经验,如果您使用
:
定义一个函数,您可能应该使用 :
调用它。此类功能通常称为“方法”。请参阅 .
和 :
在 Lua 之间的区别。
此外,我会将
printX
重命名为 getX
或完全删除它(因为它目前只是直接访问 x
是多余的)。
另请注意,默认值通常是通过将它们粘贴到类表中来实现的(在您的情况下,Vector3.x, Vector3.y, Vector3.z = 0, 0, 0
将允许您消除构造函数中的or 0
)。