在名为foo.Lua的Lua文件中,名为self.bar、foo.bar和bar的变量之间的区别是什么?
与我的示例类似的是,我正在构建一个游戏,并且有一个名为player.lua的类 几周前我编写了这个代码,当时我不知道Lua是如何工作的,所以我没有为玩家构建一张桌子 我为玩家分配了各种属性,如self.speed或self.strength。我希望(而且它是有效的)这些属性都是玩家的 我有些问题似乎找不到合乎逻辑、直观的答案 如果我在player.lua中声明了一个表(player={}),那么player.speed将引用player表的“speed”键。但如果没有这样一张桌子,我现在到底在做什么 如果我在player.lua中使用player.speed而不是self.speed呢 如果将来我想在同一个游戏中同时拥有多个玩家怎么办?如何“实例化同一类的多个实例”,就像在Java中,但在Lua中一样?这基本上会包括一个中心游戏lua文件,比如main.lua或game.lua,然后构建一个玩家表,其中每个元素本身就是一个玩家表吗 比如,listofPlayers={} 你会说: insert(listOfPlayers,player:new()),其中player:new()将使用播放器的所有默认属性实例化一个新表,然后返回该表 那么我什么时候使用元表?元表 元表用于重载语言中的常见操作。这些操作可以包括加法、乘法、相等比较和(顾名思义)类似于表的操作,例如通过键在名为foo.Lua的Lua文件中,名为self.bar、foo.bar和bar的变量之间的区别是什么?,lua,coronasdk,Lua,Coronasdk,与我的示例类似的是,我正在构建一个游戏,并且有一个名为player.lua的类 几周前我编写了这个代码,当时我不知道Lua是如何工作的,所以我没有为玩家构建一张桌子 我为玩家分配了各种属性,如self.speed或self.strength。我希望(而且它是有效的)这些属性都是玩家的 我有些问题似乎找不到合乎逻辑、直观的答案 如果我在player.lua中声明了一个表(player={}),那么player.speed将引用player表的“speed”键。但如果没有这样一张桌子,我现在到底在做
表[key]
访问值
元表通常用于在Lua中实现面向对象编程。驱动此操作的主要机制是使用\uu索引
。本例将以最基本的形式说明这一点:
>>> parent = {parentID = 'Secret'}
>>> child = {}
>>> setmetatable(child,{__index=parent})
>>> =child.parentID
Secret
键parentID
实际上不存在于child中,因此child中没有类似的东西:
child = {
parentID = 'Secret'
}
相反,我们将其设置为当有人查找不存在于子项
中的键时,我们会在父项
中查找,这是在元表中设置的,我们在中分配给表:
>>> setmetatable(child,{__index=parent})
因此,当我们请求child.parentID
时,从编程的角度来看,事件流是:
child
是否包含键为“parentID”
的键、值对?不,因此转到2子项
是否在其元表中定义了\u索引
?是的,去3号\uu index
引用的表以检查键“parentID”
parent[“parentID”]
\u index
元表方法在表示所有玩家信息的表和每个玩家自身之间建立关系,如下所示:
Player = { }
Player_metatable = {
__index = Player --look for the missing key in the Player table
}
function Player.new(name)
aPlayer = { name = name }
setmetatable(aPlayer,Player_metatable)
return aPlayer
end
function Player:rotate()
print("I'M ROTATING",tostring(self))
end
henry = Player.new("Henry")
henry:rotate()
当我们调用Player.new(“Henry”)
时,我们创建了一个表,并将其元表设置为Player\u metatable
,就像在第一个示例中设置child
的元表一样。然而,我们只是在一个函数中进行,而不是在球棒的直线上进行,没有区别
当我们调用henry:rotate()
时,如上所述的情况是:我们在henry
中查找一个键“rotate”
,但没有找到,所以我们在Player
中查找(因为在我们的元表中,\u index
指向该表)。这里有一个与该键相关的函数。然后我们调用这个函数,因为t:function
语法将我们自己传递进来
要创建类的实例,只需指定一个表,即指向定义类行为的表的元表。因此,我们可以创建任意数量的玩家:
my_player_name = Player.new(...)
修改
Player
表中的值将反映在具有关联元表的所有表中。从其他类继承的另一种方法是复制所有方法,可能通过“new”方法。在这是你可以混合和匹配从许多类。
Lua只需复制对该方法的引用,因此内存开销最小
prototype={}
--add some methods to prototype
function prototype:new()
local newtable={}
for k,v in pairs(self) do
newtabke[k]=v
end
return newtable
end
HennyH很好地描述了元表是如何使用的,以及它们给了您什么,但是为了直接回答您的问题,假设您的播放器表包含一个方法
name
:
local Player = {}
local name
function Player:name()
return self.name -- #1
return Player.name -- #2
return name -- #3
end
- #1使用
表的self
字段,这是您大部分时间使用的,因为它允许使用元表来实现类继承name
将引用调用的任何表self
方法(如果该方法是通过name
引用找到的,则可能不是\u index
)Player
- #2使用
表的Player
字段,忽略对实际name
对象的任何引用。如果您想拥有一些不受继承类影响的特定于播放器的数据,这可能很有用self
- #3使用局部变量。它在许多方面与Player.name类似,但有一个显著的区别:它允许您实现“类”的私有元素。请注意,一些使用
类的代码可以随意访问和修改Player
。当此方法作为访问Player.name
的唯一方法(当它是一个局部变量时)使用时,情况并非如此,而是通过将此变量作为upvalue的闭包。如果您不提供修改它的方法,它将是只读的name
每个选项都有自己的用途,但#1可能是您最常看到的;您可能希望提到,如果在步骤4中找不到键,那么将检查父级的元表,以便可以对其进行链接