经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
Lua编程
来源:cnblogs  作者:movin2333  时间:2021/2/18 14:58:28  对本文有异议

一.lua环境安装

1.SciTE安装包

Github 下载地址:https://github.com/rjpcomputing/luaforwindows/releases

2.LuaDist(官方推荐,但不是很好用)

http://luadist.org/

二.lua中的注释

1.单行注释--

  1. --这里是单行注释

2.多行注释

  1. --[[
  2. 这里是多行注释
  3. ]]--

小技巧:在多行注释中,--[[添加一个短横线变成---[[就可以取消多行注释

三.标示符命名规则

使用大小写字母或下划线开头,加上0个或若干个大小写字母、数字或下划线。

注意:lua中内部全局变量基本使用下划线加上大写字母命名,因此不推荐这种方式命名标示符,避免冲突。

四.lua中的数据类型

1.数据类型nil

lua中的空值类型,删除变量时将变量设置为nil值即可。没有声明的变量的值都是nil。

  1. b = 1
  2. print(b)
  3. b = nil
  4. print(b)

 

 2.数据类型boolean

布尔值只有两个值true和false,表示真和假。值得注意的是,lua中在作逻辑判断时(如分支结构或循环结构中的真假判断),false和nil都视为假,true和其他值都视为真。

  1. if nil then
  2. print(' ')
  3. else
  4. print(false)
  5. end
  6.  
  7. if 1 then
  8. print(true)
  9. end

 

 3.数据类型number

lua中的数字都是number类型,可以理解为就是c中的double类型。number有如下写法:

  1. print(2)
  2. print(2.2)
  3. print(2e3)
  4. print(2.34e5)
  5. print(3.1e-2)

 

 4.数据类型string

字符串类型使用单引号或双引号引用都可以,也可以使用两个中括号[[]]来引用字符串。

  1. print('我是字符串')
  2. print("我是字符串")
  3. print([[我是字符串]])

 

 字符串的拼接使用..,不能使用+号。

  1. print('lua中的+号会自动将'..'字符串两边的字符串转化为数字')
  2. print('2'..3)
  3. print('2'+'3')
  4. print(2+3)
  5. print('2'+3)
  6. print('2+3')
  7. print('a'+3)

 

 使用#获得字符串的字节数。

  1. print(#'aaa aa')
  2. print(#'中文一个字符占用两个字节')

 

 5.数据类型table

表的构造和基本使用。当定义table时直接定义值,不定义键时,table和string一样,可以使用#获得table中值的个数(本质上是取得最大索引)。

  1. tab1 = {} --空表 {}构造表达式
  2. tab2 = {key1='value1',key2='value2'} --使用键值对的形式构造表(和mapdictionary等类似)
  3. tab3 = {'value1','value2','value3'} --直接给出表的值,默认索引为1,2,3,4...,和数组或list等的性质类似
  4.  
  5. print(tab1) --直接打印表,打印的是表的地址
  6. print(tab1.key) --表中没有的键对应值为nil
  7.  
  8. print(tab2.key1) --获取表中的某个索引对应值的方法一
  9. print(tab2['key1']) --获取表中某个索引对应值的方法二
  10.  
  11. print(tab3[2]) --没有给出索引的表默认索引是1,2,3,4...,不能使用方法一获取索引对应的值
  12. print(tab3['1']) --索引的类型是number,使用字符1进行取值不能取得值
  13.  
  14. --使用循环遍历表
  15. for k,v in pairs(tab3) do
  16. print(k..':'..v)
  17. end

 表的添加值

  1. tab = {}
  2. tab.key1 = 'value1'
  3. tab.key2 = 'value2' --索引是字符串使用.赋值,使用中括号赋值会报错
  4. tab[10] = 100 --索引是number及其他类型使用中括号进行赋值,使用.赋值同样报错。nil不能作为索引。
  5. tab[false] = 10
  6.  
  7. print(tab.key1) --同样的,在获取值时也需要注意取值的方式
  8. print(tab[key2])
  9. print(tab[10])
  10. print(tab[false])

 

 6.数据类型function

使用function定义函数,不需要返回值,参数也不需要定义类型。

  1. function fact(n)
  2. if n==1 then
  3. return n
  4. else
  5. return n*(fact(n-1))
  6. end
  7. end
  8.  
  9. print(fact(4))

 

 函数同样可以作为值进行传递。

  1. function fact(n)
  2. if n==1 then
  3. return n
  4. else
  5. return n*(fact(n-1))
  6. end
  7. end
  8.  
  9. print(fact(4))
  10. fact2 = fact
  11. print(fact2(5))

 

 函数也可以作为参数传递,甚至可以定义匿名函数(类似于委托)。

  1. --定义测试函数
  2. function testFun(tab,fun)
  3. for k,v in pairs(tab) do
  4. fun(k,v)
  5. end
  6. end
  7.  
  8. --定义表和参数中的函数
  9. tab = {key1='value1',key2='value2'}
  10. function f(k,v)
  11. print(k..':'..v)
  12. end
  13.  
  14. --调用测试函数
  15. testFun(tab,f)

  1. --定义测试函数
  2. function testFun(tab,fun)
  3. for k,v in pairs(tab) do
  4. fun(k,v)
  5. end
  6. end
  7.  
  8. --定义
  9. tab = {key1='value1',key2='value2'}
  10. --调用测试函数,以匿名函数的形式传递函数参数
  11. testFun(tab,
  12. function (k,v)
  13. print(k..' '..v)
  14. end
  15. )

 

 7.数据类型thread

thread(线程)本质上是协程。

8.数据类型userdata

userdata是用户自定义的数据类型,通常由C/C++创建。

五.语法

1.全局变量和局部变量

lua中的变量不需要声明类型,默认情况下,变量都是全局变量。可以使用local关键字声明局部变量,局部变量只在当前代码块中起作用。一般情况下, 访问局部变量的速度更快。

  1. function test()
  2. a = 5
  3. local b = 6
  4. end
  5. test()
  6. print(a)
  7. print(b)

 2.变量的赋值

变量可以单个赋值,也可以多个同时赋值,赋值的数据类型也可以不同。也可以使用多变量赋值方便地交换变量的值。

  1. --可以单变量赋值,也可以多变量赋值
  2. a = 1
  3. a,b = 1,2
  4. a,b,c = 1,'a',3
  5.  
  6. print(a,b,c)
  7. --交换两个变量的值
  8. a,b = b,a
  9. print(a,b,c)
  10. --交换三个变量的值
  11. a,b,c = c,a,b
  12. print(a,b,c)
  13. --变量的个数多于值,多出来的变量会被自动忽略;值的个数多于变量,多出来的值会被自动忽略
  14. c,d,e = 1,2
  15. f,g = 4,5,6
  16. print(c,d,e,f,g)

 

 3.循环

while循环。

  1. i = 1
  2. while i<=5 do
  3. print(i)
  4. i=i+1
  5. end

 

 for循环。之前也有用到过遍历表的for循环,类似于foreach的使用。

  1. --i1自增到5,每次自增1
  2. for i=1,5 do
  3. print(i)
  4. end
  5.  
  6. --i1自增到10,每次自增2
  7. for i=1,10,2 do
  8. print(i)
  9. end

 

 repeat until循环。这个循环相当于do...while,但是和do...while有所不同。do...while是先执行一次do中的代码块,再判断while的逻辑语句,如果满足条件继续执行;repeat until是先执行一次until中的代码块,再判断until中的逻辑语句,如果不满足条件继续执行。

  1. i = 1
  2. repeat
  3. print(i)
  4. i=i+2
  5. until i>10

 

 4.分支结构

  1. --if语句
  2. if 0 then
  3. print(0)
  4. end
  5.  
  6. --if else语句
  7. i = 1
  8. if i<=0 then
  9. print(0)
  10. else
  11. print(1)
  12. end
  13.  
  14. --if else if ...语句
  15. j = -2
  16. if j <0 then
  17. print(-1)
  18. elseif j==0 then
  19. print(0)
  20. else
  21. print(1)
  22. end

 注:循环结构和分支结构中的,while、for、if等语句后面跟上逻辑语句,这些逻辑语句可以使用括号括起来,也可以使用空格隔开,不使用括号,这里都没有使用括号。

 

 5.函数

在lua中,函数可以作为数据赋值,也可以作为参数传递。

  1. local function max(num1,num2)
  2. if num1 < num2 then
  3. return num2
  4. else
  5. return num1
  6. end
  7. end
  8.  
  9. print(max(3,-5))
  10. --函数作为数据赋值
  11. temp = max
  12. print(temp(1,8))
  13. myprint = function (param)
  14. print('this is my print function '..param)
  15. end
  16. myprint('ww')
  17. --函数作为参数传递
  18. function add(num1,num2,printFun)
  19. res = num1+num2
  20. printFun(res)
  21. end
  22. add(40,50,myprint)
  23. --lua中的函数可以返回多个值
  24. function temp()
  25. return 10,20,30,40
  26. end
  27. res1,res2,res3,res4 = temp()
  28. print(res1,res2,res3,res4)
  29. --lua中的函数参数个数可变,如print函数
  30. --...代表可变的参数,这些参数会被封装为一个名称为arg的表,使用表的方式访问这些参数,在使用for循环遍历表时arg会多一个值表示参数个数
  31. --可变参数前可以有其他参数,但是可变参数一定在参数列表的最后,封装时只有可变参数部分会被封装到表arg
  32. function test(a,...)
  33. for k,v in pairs(arg) do
  34. print(v)
  35. end
  36. end
  37. test(1,2,3)

 六.lua中的运算符

1.算数运算符+、-、*、/、%、^(幂运算符在c#语言中不存在,c#中使用函数求幂)

2.关系运算符==、~=(不等于、 <、>、<=、>=

3.逻辑运算符and、or、not

  1. print(3>2 and 4>3)
  2. print(false or false)
  3. print(not true)

 

 七.lua中的常见API

1.string有关的API

常见转义字符:\n 换行、\\ 一个反斜杠、\" 双引号、\' 单引号

  1. a = 'hello\n\world my name is \'Micheal\''
  2. print(a)

 

string.upper 将字符串转换为全部大写 string.lower 将字符串转化为全部小写

  1. str = 'Hello everybody'
  2. str2 = string.upper(str)
  3. print(str,str2)
  4. str3 = string.lower(str)
  5. print(str,str3)

 

 string.gsub 将指定的字符替换为其他指定的字符

  1. str = 'Hello everybody'
  2. --str中的字符e替换为字符8
  3. str2 = string.gsub(str,'e','8')
  4. print(str,str2)
  5. --str中的字符e替换为字符123,最多替换1
  6. str3 = string.gsub(str,'e','123',1)
  7. print(str,str3)

 

 string.find 查找指定字符的第一个索引

  1. str = 'Hello everybody'
  2.  
  3. --从头查找'every'字符的索引(索引从1开始)
  4. index = string.find(str,'every')
  5. print(index)
  6. --从第6个字符开始茶轴'o'字符的索引
  7. index2 = string.find(str,'o',6)
  8. print(index2)

 

 string.reverse 反转字符串

  1. str = 'Hello everybody'
  2. str2 = string.reverse(str)
  3. print(str2)

 string.format 字符串格式化输出(未知number使用%d代替,未知string使用%s代替,其他代替格式可以自行查阅)

  1. num1 = 5
  2. num2 = 10
  3. str = string.format('加法:%d+%d=%d',num1,num2,num1+num2)
  4. print(str)
  5. date,month,year = 30,1,2021
  6. d = string.format('日期:%02d/%02d/%03d',date,month,year)
  7. print(d)

 

 string.char 将指定的数字转化为对应字符 string.byte 将字符转化为数字(默认转化字符串第一个字符,也可以指定转化第几个字符)

  1. print(string.char(97,98,99,100))
  2. print(string.byte('abcd'))
  3. print(string.byte('abcd',3))

 

 string.len 获得指定字符串的长度(和#的结果相同)

  1. print(string.len('我有一个梦想'))

 

 string.rep 得到指定字符串重复指定次后的字符串

  1. print(string.rep('我有一个梦想',5))

 

 string.gmatch 正则表达式匹配,返回一个迭代器

  1. for word in string.gmatch('Hello lua user','%a+') do
  2. print(word)
  3. end

 

 2.table有关的API

lua中array本质上是table。因为table是动态的,因此lua中的array也是动态的。值得注意的是,table中的默认索引是从1开始的,因此array中的默认下标也是从1开始的。下面是一个二维数组的例子:

  1. array = {}
  2. for i=1,4 do
  3. array[i] = {}
  4. for j=1,3 do
  5. array[i][j]=i*j
  6. end
  7. end
  8.  
  9. for i=1,4 do
  10. for j=1,3 do
  11. print(array[i][j])
  12. end
  13. end

 数组的遍历。

  1. array = {'lua','c#','java'}
  2. --迭代函数一pairs:遍历table中的keyvalue
  3. for k,v in pairs(array) do
  4. print(k,v)
  5. end
  6.  
  7. --迭代函数二ipairs:从索引1开始,递增遍历,遇到nil就停止
  8. for k,v in ipairs(array) do
  9. print(k,v)
  10. end
  11. array[2] = nil
  12.  
  13. for k,v in ipairs(array) do
  14. print(k,v)
  15. end

表可以当作引用类型使用,表赋值给其他表赋值的是地址引用。

  1. table = {'a','b','c'}
  2. newtable = table
  3. print(table[2])
  4. print(newtable[2])
  5. newtable[2] = 'd'
  6.  
  7. print(table[2])
  8. print(newtable[2])

 

 表的数据拼接。

  1. table1 = {'a','b','c'}
  2. --直接拼接
  3. str = table.concat(table1)
  4. print(str)
  5. --使用,间隔开拼接的数据
  6. str = table.concat(table1,',')
  7. print(str)
  8. --使用,间隔开数据,指定拼接的索引
  9. str = table.concat(table1,',',2,3)
  10. print(str)

 

 表的数据插入和移除。

  1. table1 = {'lua','c#','java','php'}
  2. print(table.concat(table1,','))
  3. --直接插入到末尾
  4. table.insert(table1,'javascript')
  5. print(table.concat(table1,','))
  6. --指定插入到哪一位,后面的数据依次向后移动一位
  7. table.insert(table1,2,'c++')
  8. print(table.concat(table1,','))
  9. --移除表一位数据
  10. table.remove(table1)
  11. print(table.concat(table1,','))
  12. --移除指定位置的数据
  13. table.remove(table1,3)
  14. print(table.concat(table1,','))

 

表的排序。

  1. table1 = {'lua','c#','java','php','c++','javascript'}
  2. print(table.concat(table1,','))
  3. --排序,按照ASCII码表顺序排列
  4. table.sort(table1)
  5. print(table.concat(table1,','))

 

八.面向对象编程及其他特性

1.模块与包

lua中的模块相当于c#的命名空间或java的包。

  1. --定义模块,这个模块保存为文件Module.luavar = 'movin'
  2.  
  3. func1 = function()
  4. print('这是一个函数')
  5. end
  6.  
  7. return module
  1. --引入模块
  2. require 'Module'
  3.  
  4. --使用模块中的变量
  5. print(var)
  6. func1()

 lua中的包是指使用C包,lua和C很容易结合,lua就是使用C写成的。

2.元表

lua提供了元表允许我们改变table的行为,每种行为关联了对应的元方法。

  1. mytable = {'lua','java','c#','c++'} --普通表
  2. mymetatable = {} --元表 拓展了普通表的行为
  3. mytable = setmetatable(mytable,mymetatable) --关联元表和普通表

1)__index元方法,这是metatable中最常用的键。当通过键访问table的时候,如果这个键没有值,那么lua就会寻找该table的metatable中的__index键。如果__index包含一个表格,lua会在表中查找相应的键,如果__index包含一个函数,lua就会调用那个函数。

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __index=function (tab,key)
  4. return 'javascript'
  5. end
  6. }
  7. mytable = setmetatable(mytable,mymetatable)
  8. print(mytable)
  9. print(mymetatable) --表和元表关联,但是两个表并不相同,元表是表的拓展
  10. print(mytable[1]) --存在的键值
  11. print(mymetatable[1])
  12. print(mytable[10]) --不存在的键值,调用元表中__index键对应的函数
  13. print(mymetatable[10])

 

 2)__newindex元方法,当对表的新索引进行赋值时会起作用,并且会取消赋值操作。

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __newindex = function (tab,key,value)
  4. print(string.format('我们要修改的key为%s,value为%s',key,value))
  5. end
  6. }
  7. mytable = setmetatable(mytable,mymetatable)
  8. --下面这些操作都不会触发__newindex对应的方法
  9. mytable[1] = 'javascript'
  10. print(table.concat(mytable,' '))
  11. table.insert(mytable,'lua')
  12. print(table.concat(mytable,' '))
  13. table.insert(mytable,3,'c')
  14. print(table.concat(mytable,' '))
  15. table.remove(mytable,1)
  16. print(table.concat(mytable,' '))
  17. table.remove(mytable)
  18. print(table.concat(mytable,' '))
  19. mytable[5] = 'lua' --对新索引进行赋值时会调用__newtable对应的方法,而且不会进行赋值操作
  20. print(table.concat(mytable,' '))

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __newindex = function (tab,key,value)
  4. rawset(tab,key,value) --由于调用了__newindex对应的函数后不会进行赋值,若想赋值,可以使用rawset函数(如果直接赋值会产生死循环)
  5. --mytable[5] = 'lua' 这里采用这种方式赋值会产生死循环
  6. end
  7. }
  8. mytable = setmetatable(mytable,mymetatable)
  9. mytable[5] = 'lua'
  10. print(table.concat(mytable,' '))

  1. mytable = {'lua','java','c#','c++'}
  2. newtable = {}
  3. mymetatable = {
  4. __newindex = newtable --__newindex对应的是一个表
  5. }
  6. mytable = setmetatable(mytable,mymetatable)
  7. mytable[5] = 'javascript' --设置不存在的索引的值时会设置到__newindex对应的表中
  8.  
  9. print(mytable[5])
  10. print(newtable[5]) --__newindex对应的表中,索引值还是5

 

 3)操作符元方法。

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __add = function(tab,newtab) --__add索引的值定义了表的加法操作,这里将第二个相加的表的所有键值对拼接到第一个表的最后
  4. for k,v in pairs(newtab) do
  5. table.insert(tab,v)
  6. end
  7.  
  8. return tab
  9. end
  10. }
  11. mytable = setmetatable(mytable,mymetatable)
  12. newtable = {'python','php'}
  13. print(table.concat(mytable+newtable,' '))

 

除了__add外,对应其他运算的元方法有:__sub(减法)__mul(乘法)__div(除法)__mod(求模)__pow(乘方)__unm(取负)__concat(连接)__eq(是否相等)__lt(小于)__le(小于等于)

 4)__call元方法

将表当作函数调用时调用__call对应的函数。

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __call = function(tab,arg)
  4. print(arg)
  5. end
  6. }
  7. mytable = setmetatable(mytable,mymetatable)
  8. mytable('我是大帅比')

 

 5)__tostring元方法

将表当作字符串使用(如print(table))时定义表对应的字符串。

  1. mytable = {'lua','java','c#','c++'}
  2. mymetatable = {
  3. __tostring = function(tab)
  4. str = ''
  5. for k,v in pairs(tab) do
  6. str = str..k..' '..v..','
  7. end
  8. return str
  9. end
  10. }
  11. mytable = setmetatable(mytable,mymetatable)
  12. print(mytable)

 

 3.协程

定义和启动协程。

方式一:

  1. --定义协同函数
  2. co = coroutine.create(
  3. function (a,b) --必须是匿名函数
  4. print(a+b)
  5. end
  6. )
  7. --运行协同函数
  8. coroutine.resume(co,20,40)

 

 方式二:

  1. --定义协同函数
  2. co = coroutine.wrap(
  3. function (a,b) --必须是匿名函数
  4. print(a+b)
  5. end
  6. )
  7. --运行协同函数
  8. co(20,40)

 

 协程的挂起和继续运行。

  1. --定义协同函数
  2. co = coroutine.create(
  3. function (a,b)
  4. print(a+b)
  5. coroutine.yield() --挂起协同函数
  6. print(a-b)
  7. end
  8. )
  9. --运行协同函数
  10. coroutine.resume(co,20,40)
  11. --这句代码的位置在运行协同函数的代码后,在重启协同函数的代码前,因此挂起协同函数后会运行这段代码
  12. print("I'm here")
  13. --继续运行协同函数
  14. coroutine.resume(co)

 

 协同程序的返回值。

  1. co = coroutine.create(
  2. function (a,b)
  3. return a+b,a-b
  4. end
  5. )
  6. --协同函数默认有一个boolean类型的返回值表示是否启动成功,自己定义的其他返回值作为第二个、第三个......等返回值
  7. res1,res2,res3 = coroutine.resume(co,20,40)
  8. print(res1,res2,res3)

  1. co = coroutine.create(
  2. function (a,b)
  3. print('........................')
  4. coroutine.yield(a+b,a-b)
  5. print('........................')
  6. return a*b,a/b
  7. end
  8. )
  9. --当协同函数中间被暂停时,可以分阶段返回不同的返回值,使当前阶段暂停的yield函数括号中的参数作为当前阶段的返回值
  10. res1,res2,res3 = coroutine.resume(co,20,40)
  11. print(res1,res2,res3)
  12. --最后一个运行阶段的返回值为return返回的内容
  13. res4,res5,res6 = coroutine.resume(co)
  14. print(res4,res5,res6)

 

 协程的状态(3种)。

  1. co = coroutine.create(
  2. function (a,b)
  3. print(coroutine.status(co)) --running运行
  4. print('........................')
  5. coroutine.yield()
  6. print('........................')
  7. print(coroutine.status(co)) --running运行
  8. end
  9. )
  10. print(coroutine.status(co)) --suspended暂停
  11. coroutine.resume(co,20,40)
  12. print(coroutine.status(co)) --suspended暂停
  13. coroutine.resume(co)
  14. print(coroutine.status(co)) --dead死亡

 

 获取正在运行的协程。

  1. co = coroutine.create(
  2. function (a,b)
  3. print(coroutine.running()) --获取正在运行的协程
  4. end
  5. )
  6. coroutine.resume(co,20,40)

 

 4.文件I/O

文件的简单读取和写入。

  1. f = io.open('iotest.txt','r') --打开文件
  2. io.input(f) --创建输入流
  3. print(io.read()) --read函数读取一行
  4. print(io.read())
  5. print(io.read())
  6. print(io.read())
  7. io.close() --关闭流

 open函数的第一个参数是文件的相对地址和名称,第二个参数是可选参数,对应打开方式。打开方式有:r(只读,文件必须存在)、w(只写,写入的文件原有数据会被清空,文件不存在会自动创建文件)、a(以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留)、r+(以可读写方式打开文件,该文件必须存在)、w+(打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件)、a+(与a类似,但此文件可读可写)、b(二进制模式,如果文件是二进制文件,可以加上b)

  1. f = io.open('iotest.txt','a') --打开文件,a为追加的形式只写,w为清空后只写
  2. io.output(f) --创建输出流
  3. print(io.write('')) --write函数写入内容,返回值代表是否写入成功
  4. io.close() --关闭流

 

 read函数的参数。参数有:"*n"(读取一个数字并返回)、"*a"(从当前位置读取整个文件)、"*l"(默认参数,读取下一行)、number(返回指定个数的字符串)。

  1. f = io.open('iotest.txt','r')
  2. io.input(f)
  3. print(io.read("*l")) --读取一行
  4. print(io.read("*n")) --读取一个数字
  5. print(io.read(10)) --读取10个字符
  6. print(io.read("*a")) --读取剩下的所有内容
  7. io.close()

 

 完全模式。完全模式下,可以同时处理多个文件。

  1. f = io.open('iotest.txt','r')
  2. --使用f:read代替io.read
  3. print(f:read())
  4. file.close()

 

 5.lua实现面向对象编程

lua中并没有直接实现面向对象编程,但是可以使用表间接实现面向对象。

  1. --定义一个人的对象
  2. person = {name='movin',age=18}
  3. person.eat = function ()
  4. print(person.name..'在吃饭')
  5. end
  6. person.eat()

 

 优化面向对象的实现。

  1. --定义一个人的对象
  2. person = {name='movin',age=18}
  3. --将对象自身作为变量传递,否则这里对象的名称不能修改
  4. person.eat = function (self)
  5. print(self.name..'在吃饭')
  6. end
  7. person.eat(person)

  1. --定义一个人的对象
  2. person = {name='movin',age=18}
  3. --使用冒号定义和调用,不用传递self参数,其中self就指代调用者
  4. function person:eat()
  5. print(self.name..'在吃饭')
  6. end
  7. person:eat()

 

 根据模板创建新对象。

  1. Person = {name='movin',age=18}
  2. function Person:eat()
  3. print(self.name..'在吃饭')
  4. end
  5.  
  6. --创建新的对象的new方法
  7. function Person:new()
  8. local t = {}
  9. --使用元表的__index元方法指向Person对象
  10. setmetatable(t,{__index=self})
  11. return t
  12. end
  13. person1 = Person:new()
  14. person2 = Person:new()
  15. print(person1.name)
  16. person2:eat()
  17. --修改对象中的属性值相当于在对象中设置了新值,再查找这个索引对应的值时就不会在Person中查找,相当于实现了修改属性和重写方法的效果
  18. person1.name = 'ww'
  19.  
  20. print(person1.name)

 

 __index元方法相当于实现了继承,元表相当于父表。当子表中没有某个属性或方法时,从父表中查找;当子表中重新赋值了某些属性或重写了某些方法时,就直接从子表中调用。

 

原文链接:http://www.cnblogs.com/movin2333/p/14348703.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号