Lua笔记

只是为了防止忘记而写的记录。

 

1.表的构造,所有的索引值都必须用[ ]表示,如果是字符串,可以去掉引号和中括号

2.  a and b  如果a为 false,返回a,否则b

     a or b 如果a为真,返回a,否则b

3.

  1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2 --倒置的链表
  3 list  = nil
  4 for i = 1, 10 do
  5     list = { next = list, value = i}
  6 end
  7 
  8 local l = list
  9 while l do
 10     print(l.value)
 11     l = l.next
 12 end
 13 
 14 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 15 --队列
 16 List = {}
 17 function List.new()
 18     return {fisrt = 0, last = 0}
 19 end
 20 function List.push(Q,value)
 21     local last = Q.last + 1
 22     Q[last] = value
 23     Q.last = last
 24 end
 25 
 26 function List.pop(Q)
 27     local first = Q.first + 1
 28 
 29     if first > Q.last then return error("error") end
 30     Q.first = first
 31     return Q[first-1]
 32 end
 33 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 34 串行化:
 35 function serialize(o)
 36     if type(o) == "number" then
 37         io.write(o)
 38     elseif type(o) == "string" then
 39         --string.format函数的"%q"参数可以转义字符串中的元字符。
 40         io.write(string.format("%q",o))
 41     elseif type(o) == "table" then
 42         io.write("{\n")
 43         --迭代table中的各个元素,同时递归的写出各个字段的value。
 44         --由此可以看出,这个简单例子可以支持嵌套的table。
 45         for k,v in pairs(o) do
 46             --这样做是为了防止k中包含非法的Lua标识符。
 47             io.write(" ["); serialize(k); io.write("] = ")
 48             serialize(v)
 49             io.write(",\n")
 50         end
 51         io.write("}\n")
 52     else
 53         error("cannot serialize a " .. type(o))
 54     end
 55 end
 56 
 57 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 58 元表的应用:
 59 Set = {}
 60 local mt = {}
 61 
 62 function Set.new(L)
 63     local set = {}
 64     setmetatable(set,mt)
 65     for _,v in pairs(L) do
 66         set[v] = true
 67     end
 68     return set
 69 end
 70 
 71 function Set.union(a,b)
 72     local cur = {}
 73     for i in pairs(a) do
 74         cur[i] = true
 75     end
 76 
 77     for i in pairs(b) do
 78         cur[i] = true
 79     end
 80     return cur
 81 end
 82 
 83 function Set.intersection(a,b)
 84     local cur = {}
 85     for v in pairs(a) do
 86         cur[v] = b[v]
 87     end
 88     return cur
 89 end
 90 
 91 function Set.tostring(set)
 92     local l = {}
 93     for e in pairs(set) do
 94         l[#l+1] = e
 95     end
 96     return "{"..table.concat(l,",").."}"
 97 end
 98 
 99 function Set.print(s)
100     print(Set.tostring(s))
101 end
102 
103 mt.__add = Set.union
104 
105 s1 = Set.new({10,20,30,50})
106 s2 = Set.new({15,25,35,60})
107 
108 s3 = s1+s2
109 Set.print(s3)
110 
111 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112 __newindex元方法与__index类似,__newindex用于更新table中的数据,
113 而__index用于查询table中的数据。当对一个table中不存在的索引赋值时,在Lua中是按照以下步骤进行的:
114 1.Lua解释器先判断这个table是否有元表;
115 2.如果有了元表,就查找元表中是否有__newindex元方法;如果没有元表,就直接添加这个索引,然后对应的赋值;
116 3.如果有这个__newindex元方法,Lua解释器就执行它,而不是执行赋值;
117 4.如果这个__newindex对应的不是一个函数,而是一个table时,Lua解释器就在这个table中执行赋值,而不是对原来的table。
118 
119 __index 例子:
120 Windows = {}
121 
122 Windows.default = {
123     x = 0,y = 0,with = 100,heigh = 200,
124     color = {
125         r = 255, g = 255, b = 255
126     }
127 }
128 
129 function Windows.tostring(s)
130     if type(s) == "number" then
131         io.write(s)
132     elseif type(s) == "string" then
133         io.write(string.format("%q",s))
134     elseif type(s) == "table" then
135         io.write("{")
136         for key,value in pairs(s) do
137             io.write("["); io.write(Windows.tostring(key)); io.write("] = ")
138             io.write(Windows.tostring(value))
139             io.write(",\n")
140         end
141         io.write("}")
142     else
143         error("cannot tostring!!!");
144     end
145 end
146 
147 function Windows.print(s)
148     return print(Windows.tostring(s))
149 end
150 Windows.mt = {} -- 创建元表
151 
152 function Windows.new(o)
153     setmetatable(o,Windows.mt)
154     return o
155 end
156 
157 Windows.mt.__index = function (table ,key)
158     return Windows.default[key]
159 end
160 
161 local win = Windows.new{x = 10, y = 20 }
162 
163 
164 Windows.print(win.x)
165 Windows.print(win.with)
166 Windows.print(win.color)
167 
168 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169 实现类和对象的例子:
170 p中有没有talk这个键? 有 --> 返回talk对应的值
171         |
172        没有
173         |
174 p中是否设置过metatable? 否 -->  返回nil
175         |
176 177         |
178 在p的metatable中有没有__index这个键? 没有 -->  返回nil
179         |
180 181         |      
182 在p的metatable中的__index这个键对应的表中有没有talk这个键? 没有 --> 返回nil
183         |
184         有,返回getmetatable(p).__index.talk
185         
186         
187 Person = {name = "我是一个懒人"} --
188 
189 Person.__index = Person --重定义元表的索引  设置Person类的__index为自己
190 function Person:talk(words)--类的一个方法
191     print(self.name.." 说:"..words)
192 end
193 
194 function Person:create(name)--构造函数一样
195     local p = {}
196     setmetatable(p,Person) --设置了p的元方法
197     p.name = name
198     return  p
199 end
200 
201 local pa = Person:create("路人甲A") --创建一个对象
202 local pb = Person:create("路人甲B")
203 
204 pa:talk("hello")
205 pb:talk("sb")
206 
207 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
208 类的继承的一个例子:必须理解setmetatable,__index的过程。
209 
210 -- http://blog.csdn.net/losophy/article/details/20311387
211 A  = {} --基类A
212 
213 function A:new(o) --构造方法
214     o = o or {} --如果为nil 则赋值为{}
215     setmetatable(o,self) --设置元方法,确定在谁那寻找子类,没有的方法
216     self.__index = self --这个很重要。所以理解。
217     return o
218 end
219 
220 function A:funName()
221     print("A")
222 end
223 
224 B = A:new()
225 B:funName()
226 
227 C = B:new()
228 
229 function B:funName()
230     print("B")
231 end
232 
233 C:funName()
234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235 使用__newindex设置只读模式,牛气
236 local function readOnly(t)
237     local newT = {}
238     local mt = {
239         __index = t,
240         __newindex = function()
241             error("别修改我!我是只读的!")
242         end
243     }
244     setmetatable(newT, mt)
245     return newT
246 end
247 local days = readOnly({"星期一", "星期二", "星期日"})
248 
249 print(days[2])
250 days[1]="hehe" --但调用次赋值的时候,就会找到__newindex,从而被禁止 
251 
252 ______________________________________________________________
253 a.首先,readOnly会创建一个新的table,然后把我们传进去的table作为__index元方法。
254 b.元表里还增加了__newindex,用来阻止不存在字段的赋值操作。
255 c.readOnly返回的table已经不是我们原来的table了,它是一个空的table,但是它被设置了一个新的元表。
256 d.开始对days执行赋值操作:days[2] = “星期三哪去了啊?” 。
257 e.days是一个空的table,所以它不存在这个字段,也因此,会调用__newindex元方法,赋值失败。
258 f.如果只是调用days,不进行赋值,如:print(days[2]); 则能正常输出字段值,因为days的元表里有__index元方法。虽然days中不存在2这个字段,但是可以通过__index找到这个字段。
259 总而言之,最终,days成为了一个只可以读取,不能进行赋值操作的table。
260 
261 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262 解释__newindex的作用
263 a.如果__newindex是一个函数,则在给table不存在的字段赋值时,会调用这个函数。
264 b.如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值。
265 
266 local smartMan = {
267     name = "hxl",
268     money = 9000,
269     hello = function()
270         print("hxl ni hao")
271     end
272 }
273 
274 local t = {}
275 
276 local mt = {
277     __index = smartMan,
278     __newindex = function(table,key,value)
279         print("key".."不要试图修改我,已经被禁止了!")
280     end
281 }
282 
283 setmetatable(t,mt)
284 
285 print(t.name)
286 print(t.money)
287 t.hello()
288 t.hello = "heh"
289 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
290 __index 和 __newindex的一个很牛气的例子
291  local smartMan = {
292         name = "none",
293     }
294    
295     local other = {
296         name = "大家好,我是很无辜的table"
297     }
298    
299     local t1 = {};
300    
301     local mt = {
302         __index = smartMan,
303         __newindex = other
304     }
305    
306     setmetatable(t1, mt);
307      
308     print("other的名字,赋值前:" .. other.name);
309     t1.name = "小偷";
310     print("other的名字,赋值后:" .. other.name);
311     print("t1的名字:" .. t1.name);
312 结果:
313 [LUA-print] other的名字,赋值前:大家好,我是很无辜的table
314 [LUA-print] other的名字,赋值后:小偷
315 [LUA-print] t1的名字:none
316 说明:修该的时候只会修改__newindex里面的指定的地方值,
317       查询的时候只会读出 __index里面的值.
318 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
View Code

4.

  1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2 Lua实现多重继承:
  3 
  4 
  5  function search(classes, key)--查询函数
  6     for i = 1, #classes do
  7         local value = classes[i][key];
  8         if value ~= nil then
  9             return value;
 10         end
 11     end
 12 end
 13 
 14  function createClass(...) --可变参数
 15     local parents = {...}; --保存它的可变参数
 16     local child = {};
 17 
 18     -- 设置类的元表,如果元表已经设置,就去元表里看看有没有设置__index,找有没有对应的key值.
 19     setmetatable(child, {
 20         __index = function(table, key)
 21             return search(parents, key);
 22         end
 23     })
 24 
 25     -- 给类新增一个new函数,用于创建对象
 26     function child:new()
 27         o = {};
 28         setmetatable(o, child);--设置元表,并且在自己的地方寻找有木有相对于的key值
 29         child.__index = child;--设置元表,并且在自己的地方寻找有木有相对于的key值
 30         return o;
 31     end
 32 
 33     -- 返回这个继承了多个类的子类
 34     return child;
 35 end
 36 
 37 
 38  --一个精灵类
 39     TSprite = {}
 40     function TSprite:hello()
 41         print("谁跟你hello!");
 42     end
 43 
 44     function TSprite:new()
 45         o = {}
 46         setmetatable(o, self);
 47         self.__index = self;
 48         return o;
 49     end
 50 
 51     -- 一个子弹类
 52     TBullet = {}
 53     function TBullet:fire()
 54         print("别动,再动我就瞄不准了!");
 55     end
 56     function TBullet:new()
 57         o = {}
 58         setmetatable(o, self);
 59         self.__index = self;
 60         return o;
 61     end
 62 
 63     -- 继承了两个类的子类
 64     local BulletSprite = createClass(TSprite, TBullet);--传入这两个table,返回对应的child
 65 
 66     -- 子类的对象
 67     local bSprite = BulletSprite:new();
 68     bSprite:hello();
 69     --[[子类对象调用hello方法,会去bSprite中寻找,
 70     发现没有,那么此时没有就去看看 bSprite有没有设置元表有的,去元表中看有没有设置__index
 71     发现也是有的,就调用它对应的方法,便进入了serch了。便可以找到了
 72     --]]
 73     bSprite:fire();
 74 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 75 弱引用:
 76 1)key值弱引用,也就是刚刚说到的情况,只要其他地方没有对key值引用,
 77 那么,table自身的这个字段也会被删除。设置方法:setmetatable(t, {__mode = “k”});
 78 2)value值弱引用,情况类似,只要其他地方没有对value值引用,
 79 那么,table的这个value所在的字段也会被删除。设置方法:setmetatable(t, {__mode = “v”});
 80 3)key和value弱引用,规则一样,但是key和value都同时生效,
 81 任意一个起作用时都会导致table的字段被删除。设置方法:setmetatable(t, {__mode = “kv”});
 82  
 83 当然,这里所说的被删除,是指在Lua执行垃圾回收的时候,并不一定是立刻生效的。
 84 我们刚刚只是为了测试,而强制执行了垃圾回收。
 85 
 86 t = {};
 87 
 88     -- 给t设置一个元表,增加__mode元方法,赋值为“k”
 89     setmetatable(t, {__mode = "k"});
 90 
 91     -- 使用一个table作为t的key值
 92     key1 = {name = "key1"};
 93     t[key1] = 1;
 94 
 95     -- 又使用一个table作为t的key值
 96     key2 = {name = "key2"};
 97     t[key2] = 1;
 98 
 99     t = {}
100     key1,key2 = t,t
101 
102     -- 强制进行一次垃圾收集
103     collectgarbage();
104 
105     for key, value in pairs(t) do
106         print(key.name .. ":" .. value);
107     end
108 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
View Code

 

posted @ 2015-03-20 14:42  芷水  阅读(203)  评论(0编辑  收藏  举报