语法糖 在讨论lua脚本的面向对象实现之前,我们先了解一个概念“语法糖(syntactic sugar)”,百度官方的解释是:
也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会
官方的东西一般都比较专业和严谨,但不好理解;我的看法就是语法糖是某种语法的别名,只是这个别名背地里多做了些事情,所以我们用的时候就不用那么麻烦。某种程度上可以理解为宏,只是宏定义多了做了些事情。比如下面的宏
#include <stdio.h>
#define ARRAY_LEN(st) do{ assert(st!=NULL); sizeof(st)/sizeof(st[0]) }while(0)
// ARRAY_LEN是求数组长度的宏,但我们额外加了assert判断,排除st为非法指针的情况
好了,这里在提前说明两个lua中用到的标点符号点号”.”和冒号“:”,冒号就是点号的语法糖,冒号比点号在背地里多做了点事情,所以比点号多一个点,^_^。
举例说名相同类的分别用“.”和“:”的实现方式
冒号
Class = {}
Class.__index = Class
function Class:new(x,y)
local o = {len=1}
setmetatable(o, Class)
--[[o.x = x
o.y = y--]]
self.x = x
self.y = y
return o
end
function Class:test()
print(self.x,self.y)
end
object = Class:new(10,20)
object:test()
object.test(object)
点号
Class = {}
Class.__index = Class
function Class.new(self,x,y)
local o = {len=1}
setmetatable(o, Class)
--[[o.x = x
o.y = y--]]
self.x = x
self.y = y
return o
end
function Class.test(self)
print(self.x,self.y)
end
object = Class:new(10,20)
object:test()
object.test(object)
两种方法运行的结果相同,如下
10 20
10 20
从上面两个例子中可以看出,用点号“.”比用冒号“:”的函数参数要多一个self或者是实例本身(object),代码上看显然用冒号的要方便的多,实际冒号也是带了self参数的,只是隐藏了,我们不需要关心。为啥要使用self呢,在lua程序设计第二版中有提到当一项操作所作用的”接受者”,需要一个额外的参数来表示该接受者,这个接受者就是self。
采用冒号写法的函数会多出一个隐藏参数self,这个self不属于Lua的关键字,但在冒号定义下会由编译器自动创建这个局部变量,如果不想用self这个名字,修改lua的源代码重新编译就可以了,只是这样一样,就不能用其它第三方库了。self的意思也很好理解,就是这个table本身,相当于C++的this指针,self指向当前作用域的父表结构,通常在函数定义中使用。
类
我们在来分析一下,lua如何使用元表的定义实现了面向对象编程,实现的方法有很多种,网上搜每一篇的形式都不同,但基本的要点是相同的。就是利用了元表的特性,派生出子类。这里以冒号的代码来说明
Class = {}
Class.__index = Class
function Class:new(x,y)
local o = {len=1}
setmetatable(o, Class)
--[[o.x = x
o.y = y--]]
self.x = x
self.y = y
return o
end
function