# 17 Lua 面向对象
Lua中的table就是一种对象,看以下一段简单的代码:
```lua
local tb1 = {a = 1, b = 2}
local tb2 = {a = 1, b = 2}
local tb3 = tb1
if tb1 == tb2 then
print ("tb1 == tb2")
else
print ("tb1 ~= tb2")
end
tb3.a = 3
print (tb1.a)
```
上述代码会输出tb1 ~= tb2。说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的。我们是基于table来实现的模块,在table中可以定义函数,也就是说,每个table对象都可以拥有其自己的操作。看一段代码:
```lua
Account = {balance = 0}
function Account.withDraw(v)
Account.balance = Account.balance - v
end
Account.withDraw(10) --调用函数
print(Account.balance)
```
上面的代码创建了一个新函数,并将该函数存入Account对象的withDraw字段中,然后我们就可以调用该函数了。不过,在函数中使用全局名称Account是一个不好的编程习惯,因为这个函数只能针对特定对象工作,并且,这个特定对象还必须存储在特定的全局变量中。如果改变了对象的名称,withDraw就再也不能工作了。例如以下代码:
```lua
Account = {balance = 0}
function Account.withDraw(v)
Account.balance = Account.balance - v
end
Account.withDraw(10) --调用函数
print(Account.balance)
a = Account
Account = nil
a.withDraw(100)
```
```lua
-10
lua: test14_class.lua:23: attempt to index a nil value (global 'Account')
stack traceback:
test14_class.lua:23: in field 'withDraw'
test14_class.lua:32: in main chunk
[C]: in ?
```
这样就会出现错误。我在这里使用Account创建了一个新的对象a,当将Account赋值为nil时,应该要对a对象不产生任何影响。但是,由于在函数withDraw内部使用了Account,而不是变量a,所以就出现了错误。如果我们将withDraw函数内部的Account.balance = Account.balance – v语句修改为:a.balance = a.balance – v,这样就不会出现错误了。这就表明,当我们需要对一个函数进行操作时,需要指定实际的操作对象,即这里的a,这就需要一个额外的参数来表示该操作者,就好比C++中的this一样,只不过这里将这个关键字换成了self,换完以后的代码如下:
```lua
Account = {balance = 0}
function Account.withDraw(self, v)
self.balance = self.balance - v
end
a = Account
Account = nil
a.withDraw(a, 100)
print (a.balance)
```
这样再调用,就不会出现错误了。
使用self参数是所有面向对象语言的一个核心。大多数面向对象语言都对程序员隐藏了self参数,从而使得程序员不必显示地声明这个参数。Lua也可以,当我们在定义函数时,使用了冒号,则能隐藏该参数,那么上述代码使用冒号来改下,就是下面这个样子了。
```lua
Account = {balance = 0}
function Account:withDraw(v) --注意这里写的是":"
self.balance = self.balance-v
end
a = Account
Account = nil
a:withDraw(100) --注意这里调用时,也需要使用":"
print(a.balance)
```
冒号的作用很简单,就是在方法定义中添加一个额外的隐藏参数,以及在一个方法调用中添加一个额外的实参。冒号只是一种语法便利,并没有引入任何新的东西;如果你愿意,你可以可以不使用self,而是在每次定义一个函数时,手动的加上self,只要你处理好了self,它们都是一样的。
这里乱乱的讲了一些Lua中的东西,主要还是说了table是一个不一样的东西,还有self。接下来,就正式进入面向对象的世界。不要忘了,上面总结的东西是非常有用的。
- 1 Lua介绍及环境
- 2 基本语法
- 3 数据类型
- 4 Lua 变量
- 5 循环
- 6 流程控制
- 7 函数
- 8 运算符
- 9 字符串
- 10 数组
- 11 迭代器
- 12 table
- 13 Lua 模块与包
- 14 Lua 元表(Metatable)
- 14.1 元表案例
- 15 Lua 协同程序(coroutine)
- 16 Lua 文件IO
- 17 Lua 面向对象
- 17.1 类
- 17.2 继承
- 17.3 封装
- 18 Lua 与 Mysql
- 19 Lua 与 redis
- 20 Lua 与 JSON
- 21 Lua 与 http
- 22 Lua 与 Nginx
- 22.1 Nginx_Lua的安装及环境
- 22.2 ngx_lua API(全表)
- 22.3 常用命令介绍
- 22 Lua 人工智能
- (1) Torch的安装
- (2)Tensor
- Lua与C混合编程