【mackler】电脑mod完全教程

这种类型的松散,可以让我们非常自如的调度函数
看如下代码,我们定义了3个不同的函数abc,然后在一个表t中建立了字符串abc和变量abc(函数)的映射
最后我可以直接根据字符串直接得到函数

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 01:04:00 +0800 CST  
如果没有如此松散的类型组织,我们需要用若干个elseif才能完成这样的功能。所以这个还是非常好的
顺便提一句,由于在lua中"="起到了赋值的作用
所以判断两个变量是否相等是用"==",不相等是"~=",大于等于是">=",小于等于"<=" 这些运算的结果都是boolean类型,可以用and or not来连接
比如a>b and b>c
这样的代码可读性还是非常高的

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 01:08:00 +0800 CST  
我们甚至可以这样把若干个函数放到一个table t里面,然后可以用t.a(),t.b(),t.c()这样的方式执行它

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 10:38:00 +0800 CST  
之前忘记提及了,三种循环语句,在循环过程中,可以通过break语句来跳出循环体
break也只能用在循环体当中,并且也只往外跳一层循环。

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 16:59:00 +0800 CST  
除了break,还有一个语句可以跳出去,那就是return
在函数当中,return可以返回一些数据,作为函数执行的返回值,例如前面提到的斐波那契数列
也可以作为一个程序的结束,因此当执行到return的时候,当前的函数或者程序就结束了,直接跳出函数或程序了。

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 17:01:00 +0800 CST  
说到return,再提一个lua的特性
等号赋值是可以多个数字进行的
例如a,b=1,2可以同时给a,b赋值
而程序的返回值也是可以有多个的
例如图中getab函数返回两个返回值。
如果等号左边的变量多一点,则多余的变量不会被赋值
如果有变的值多一点,则多余的值会被忽略

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 17:05:00 +0800 CST  
函数的return值其实是非常松散的
同一个函数甚至可以返回完全不同类型和数量的值,只要调用它的函数能够处理即可。语法是不存在问题的。
传入的参数一样非常自由,我们可以传递不同数量的参数。例如图中的函数,我们用"..."表示我们可以传递多个参数,所有的参数会放在名为arg的table中,我们可以用arg[1],arg[2]依次访问各个参数。可以用#arg得到参数的个数。也可以用for语句遍历arg的所有元素

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 17:14:00 +0800 CST  
函数也有局部函数的概念,和局部变量一样,局部函数的作用范围也只有他的块内可以用。

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 17:21:00 +0800 CST  
下面要说一些比较深入的东西了,希望大家仔细看,多动手试试,有不明白的可以回复本贴问。
在Lua语言中,每个table都有一些默认的行为,我们可以给table添加(键-值)组合到table中,也可以通过键来查询值,还可以遍历这些值。
但是我们不可以像对待number类型一样让两个table做加减法,比较大小
也不可以像对待function类型一样,执行/调用一个table
Lua中提供了一个叫做metatable的东西,可以让我们修改table的上述行为,使用metatable,我们可以给table定义加法,从而对两个table执行a+b等
lua中每个table都有自己的metatable,getmetatable(table)可以获得一个table的metatable
不过默认情况下,lua不会给新建的table的metatable赋值。
所以如果你执行上述代码,你会得到nil

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:04:00 +0800 CST  
我们可以用setmetatable(table,metatable)给一个table设置它的metatable。
如图,t是新建的一个table,我们通过setmetatable(t,t1),将t的metatable设置为t1
如果执行上述代码,我们将得到true,也就是t的metatable就是t1

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:10:00 +0800 CST  
每个table虽然有自己独立的metatable域,不过他们可以设定同一个table为他们的metatable
由于metatable是可以改变table的行为的,这样就可以定义一系列行为相同的table了
table在Lua语言中承担了面向对象编程的作用,为所有的对象设置同样的metatable提供了这种可能性,我们在后面会慢慢说面向对象编程的思路以及如何利用metatable来实现这种思路。这里只是提及一下。

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:16:00 +0800 CST  
下面开始给大家说明一下metatable的作用
如图,我们新建了一个table名为mt,并且给它的"__add"键设置了一个函数作为值。(注意这里的__add是两个"_")
这个函数的输入是2个具有x,y键的table a和b
函数最后返回了一个table 具有x,y键,并且值为a和b的x,y值相加。
接着我们定义了v1和v2两个table,并且给他们的x,y分别赋值,并且把他们的metatable都设置成mt
重点来了,我们可以进行v1+v2这样的加法运算了,注意v1和v2是两个table,他们本不可以做v1+v2这样的运算的。但是因为他们的metatable都是mt,并且mt具有__add这样一个函数。

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:30:00 +0800 CST  
类似的,我们还有__mul可以替换掉乘法运算,可以实现a*b的操作

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:32:00 +0800 CST  
此外,还有比较运算,不过__add和__mul的返回值类型没有任何限定,但是下面的比较类型必须返回boolean类型的值
__eq(a,b)相当于a==b
__lt(a,b)相当于a<b
__le(a,b)相当于a<=b

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:39:00 +0800 CST  
至于~=、>、>=三个操作,Lua会自动取反调用哒
~=相当于not ==
>相当于not <=
>=相当于not <

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 18:43:00 +0800 CST  
metadata内建的域还有__tostring
这个域是和tostring()这个函数对应的。
正常情况下一个table传递给tostring(table),得到的通常是一段如下的字符串
"table: 58cf5433"
通过定义__tostring(table),我们可以重新设置tostring作用在这个table上的效果。
而print()函数在输出任何类型的时候,都会先调用tostring将其转变成string类型再输出。
所以如图的最后print(v1)会输出(10,20)

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 19:36:00 +0800 CST  
如果我们设置了一个table的metatable之后,把我们的table给别人用的时候,不希望metatable不再被修改,可以设置__metatable域
如果这个域不为nil
getmetatable(table)将会返回这个域的值
setmetatable(table,metatable)将会报错

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 19:40:00 +0800 CST  
再介绍一个更加重要的metatable的域__index
当我们访问一个table的时候,我们会用类似table.key,table[index]的方式来获取table中某些值,而__index域定义的函数就是用来改变这种访问方式的
如图,window里面的元素只有一个prototype。正常情况下,如果我们访问window.x一定会得到nil,因为不存在这个key。但是我们重新定义了一下__index,图中的两种方法都可以
一种是直接重定向到prototype,
mt.__index=prototype,于是window.x就等价于prototype.x了
另一种是以函数的形式
mt.__index=function(table,key)从而返回正确的值
(PS:这里补充一下,table初始化的方式我前面介绍了
table={["key"]=value}的形式
其实直接table={key=value}也是可以的
访问一样,table.key和table["key"]都行)

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 19:55:00 +0800 CST  
__index域是控制table的访问
__newindex域则是控制table的更新
例如我给执行window.somekey="value",这个时候如果有__newindex函数的话,对应的操作会传递给对应的函数
当然,如果__newindex对于的是table类型的话,和index一样,直接把更新切换到对应table上。
例如,图中,如果我把__newindex那句改成
mt.__newindex=prototype
那么执行
window.somekey="value"之后
window.prototype将会增加一个somekey-"value"的组合。而不是增加在window里面

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 20:08:00 +0800 CST  
删掉了上面1楼,觉得一下子直接给大家展示面向对象编程有点Orz,我们重新来看。
试想,当我们觉得Lua语言的类型过于匮乏,无法满足某些处理需求时,比如希望Lua能为我处理向量类型,我们能不能自己定义一种向量类,并且支持向量的各种操作呢?
作为一个向量,首先它得存储它的两个分量x和y,其次,我们还需要操作它,例如设置x和y的值。
而同时可以存储各种变量和函数的,在lua中就是table这种类型。
于是我们从一个table开始,逐步改造,使其能成为我们的新类型。
如图,我们先定义了一个Vector={x=0,y=0},于是它有了2个域x和y,值都为0
接着我们又定义了在Vector的setXY域定义了一个函数,可以给我们设置x和y的值
此时我调用Vector.setXY(10,10)就设置Vector的两个分量的值为x和y了

——来自 MCLive


楼主 maple_in_thu  发布于 2014-10-14 21:38:00 +0800 CST  

楼主:maple_in_thu

字数:24301

发表时间:2014-10-12 21:33:00 +0800 CST

更新时间:2016-03-15 11:34:57 +0800 CST

评论数:395条评论

帖子来源:百度贴吧  访问原帖

 

热门帖子

随机列表

大家在看