学习Cocos2d-x Lua:调用函数时用点号还是用冒号
在这个系列中,我们将深入学习Cocos2d-x Lua,总结Lua开发过程中涉及的知识点,以及如何在开发过程中使用Cocos Code IDE。本篇文章将聚焦于初学者在Lua学习中最容易混淆的两种函数调用方式:使用点号和冒号调用函数的区别。
1. 初学者最易混淆的问题——调用函数时用点号还是用冒号?
先来看下面这两句代码:
mSprite.setPosition(100, 20)
mSprite:setPosition(100, 20)
对于初次接触Lua的开发者而言,这无疑是个令人头疼的问题。为什么函数调用会有两种形式呢?难道可以随意选择吗?实际上,这两种形式存在显著区别,不过区别仅有一处,后续会详细介绍。
2. 最简单的类
我们先从简单的示例入手,创建一个“类”:
TSprite = {
x = 0,
y = 0
}
function TSprite.setPosition(x, y)
TSprite.x = x
TSprite.y = y
end
TSprite.setPosition(1, 2)
print("TSprite坐标(" .. TSprite.x .. "," .. TSprite.y .. ")")
这里实际上是创建了一个table,并为其添加了一些字段。运行上述代码,输出结果如下:
[LUA-print] TSprite坐标(1,2)
需要注意的是,setPosition
函数内部是通过 TSprite
来调用 x
和 y
字段的。并且,我们使用点号调用 setPosition
函数,这是标准的函数调用方式,需要牢记。
3. 不用真实姓名可以吗?——self的作用
如果仔细观察,会发现上述示例存在问题。若按以下方式调用:
local who = TSprite
TSprite = nil
who.setPosition(1, 2)
这样做会报错。虽然通过 who
可以调用 setPosition
函数,但函数内部需要使用 TSprite
,而此时 TSprite
已被置为 nil
。
为了解决这个问题,我们可以这样修改代码:
TSprite = {
x = 0,
y = 0
}
function TSprite.setPosition(self, x, y)
self.x = x
self.y = y
end
local who = TSprite
TSprite = nil
who.setPosition(who, 1, 2)
print("TSprite坐标(" .. who.x .. "," .. who.y .. ")")
运行结果仍然是:
[LUA-print] TSprite坐标(1,2)
注意 setPosition
函数的第一个参数 self
,我们强制要求传入一个参数,该参数就是 TSprite
本身。在调用 setPosition
函数时,传入 who
,其内容与 TSprite
相同,这样 setPosition
函数就能正常执行了。
4. 默认的self参数,以及默认传递self参数
如果每次创建和调用函数都要手动处理 self
参数,开发者肯定会觉得麻烦。为此,Lua 提供了冒号这一便捷的使用方式。
示例代码如下:
TSprite = {
x = 0,
y = 0
}
function TSprite:setPosition(x, y)
self.x = x
self.y = y
end
local who = TSprite
TSprite = nil
who:setPosition(1, 2)
这里需要留意两点:一是 setPosition
函数的定义使用了冒号;二是 setPosition
函数的调用也使用了冒号。冒号的作用是:在定义函数时,为函数添加隐藏的第一个参数 self
;在调用函数时,默认将当前调用者作为第一个参数传递进去。使用冒号后,效果与使用点号时相同,但无需显式定义 self
参数和主动传递调用者参数。
可以说,冒号是为了方便开发者而设计的。在使用 Cocos2d-x Lua 进行开发时,大部分情况下都会使用冒号,因为多数时候需要使用 self
参数,类似于 C++ 中的 this
关键字。
5. 总结
下一篇文章将正式进入面向对象的内容,希望大家还记得元表和元方法等基础知识,这些在面向对象编程中会用到。