学习Cocos2d-x Lua:调用函数时用点号还是用冒号

2015年03月25日 11:36 0 点赞 0 评论 更新于 2017-05-09 05:08

在这个系列中,我们将深入学习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 来调用 xy 字段的。并且,我们使用点号调用 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. 总结

下一篇文章将正式进入面向对象的内容,希望大家还记得元表和元方法等基础知识,这些在面向对象编程中会用到。

作者信息

boke

boke

共发布了 1025 篇文章