1.   metatables and metamethods  
  2.   getmetatable(t)  
  3.   setmetatable(t, tm)  
  4.  1, 算术运算  
  5.   __add, __mul, __sub, __div,__unm(负数), __pow(幂)  
  6.   lua选择metamethod的原则:(第一个参数)or (第二个参数)  
  7.   意思是,第一个参数存在__add则用第一个参数,如果第一个参数不存在__add,则用第二个参数的,  
  8.   如果第二个参数不存在则报错;  
  9. 例:  
  10. Set = {}  
  11. Set.mt = {} --metatable  
  12. function Set.union(a, b) --metamethod  
  13.     local res = Set.new{}  
  14.     for k in pairs(a) do res[k] = true end  
  15.     for k in pairs(b) do res[k] = true end  
  16.     return res  
  17. end  
  18.  
  19. function Set.tostring(set)  
  20.     local s = "{" 
  21.     local sep = "" 
  22.     for e in pairs(set) do  
  23.         ss = s..sep..e  
  24.         sep = "," 
  25.     end  
  26.     return s.."}"  
  27. end  
  28.  
  29. function Set.print(s)  
  30.     print(Set.tostring(s))  
  31. end  
  32.  
  33. function Set.new(t)  
  34.     local set = {}  
  35.     setmetatable(set, Set.mt) --set metatable  
  36.     SetSet.mt.__add = Set.union  --set metamethod  
  37.     for _, l in ipairs(t) do set[l] = true end  
  38.     return set  
  39. end  
  40.  
  41.  
  42. a = Set.new{1, 3, 5, 7, 9}  
  43. b = Set.new{2, 4, 6, 8, 0}  
  44.  
  45. s = a + b  
  46. Set.print(s)  
  47.  
  48. 2, 关系运算符  
  49.    __eq(等于), __lt(小于), __le(小于等于)  
  50.  
  51. 3, 关系运算符号与算术运算符号,当遇到不支持的类型时候,都抛出异常  
  52.    但等号运算不会抛出异常  
  53.  
  54. 4, __tostring, 串格式化(print 函数总是调用tostring来格式化它的输出,而tostring总是检查__tostring域)  
  55. Set = {}  
  56. Set.mt = {}  
  57. function Set.union(a, b)  
  58.     local res = Set.new{}  
  59.     for k in pairs(a) do res[k] = true end  
  60.     for k in pairs(b) do res[k] = true end  
  61.     return res  
  62. end  
  63.  
  64. function Set.tostring(set)  
  65.     local s = "{" 
  66.     local sep = "" 
  67.     for e in pairs(set) do  
  68.         ss = s..sep..e  
  69.         sep = "," 
  70.     end  
  71.     return s.."}"  
  72. end  
  73.  
  74. function Set.new(t)  
  75.     local set = {}  
  76.     setmetatable(set, Set.mt)  
  77.     SetSet.mt.__add = Set.union  
  78.     SetSet.mt.__tostring = Set.tostring  
  79.     for _, l in ipairs(t) do set[l] = true end  
  80.     return set  
  81. end  
  82.  
  83. a = Set.new{1, 3, 5, 7, 9}  
  84. b = Set.new{2, 4, 6, 8, 0}  
  85.  
  86. s = a + b  
  87. print(s)  
  88.  
  89. 5, __metatable, 如果设置了这个域  
  90.    则getmetatable将返回这个值,而setmetatable将报错  
  91.  
  92. 6,   
  93. Set = {}  
  94. Set.mt = {}  
  95. Set.mt.__metatable = "no no no" 
  96.  
  97. setmetatable(Set, Set.mt)  
  98. print(getmetatable(Set)) --结果为"no no no"  
  99. setmetatable(Set, {}) --会报错  
  100.  
  101. 7,__index   
  102.   当我们访问一个表的不存在的域的时候,访问会触发lua解析器去查找__index方法, 如果不存在则返回nil  
  103.   否则则将这个table和它缺少的域为参数调用__index函数  
  104.   如果__index的为一个表,则直接在这个表中查找缺少值  
  105. 例1:  
  106. Window = {}  
  107. Window.prototype = {x=0y=0width=100height=100}  
  108. Window.mt = {}  
  109. function Window.new(o)  
  110.     setmetatable(o, Window.mt)  
  111.     return o  
  112. end  
  113. Window.mt.__index = function (table, key)  
  114.     return Window.prototype[key]  
  115. end  
  116. w = Window.new{x=10y = 20}  
  117. print(w.width)  
  118.  
  119. 例2:  
  120. Window = {}  
  121. Window.prototype = {x=0y=0width=100height=100}  
  122. Window.mt = {}  
  123. function Window.new(o)  
  124.     setmetatable(o, Window.mt)  
  125.     return o  
  126. end  
  127. WindowWindow.mt.__index = Window.prototype  
  128. w = Window.new{x=10y = 20}  
  129. print(w.width)  
  130.  
  131. 8, __newindex  
  132.    当你给表的一个缺少的域赋值,解释就会查找__newindex,如果__newindex是一个函数,  
  133.    如果存在则调用这个函数而不是赋值操作,  
  134.    当你给表的一个缺少的域赋值,如果__newindex是一个表,则对这个表进行赋值,而不是对原表进行赋值  
  135.    rawset(t, k, v) 不会查找__newindex  
  136.    rawget(t,k) 不会查找__index  
  137.  
  138. 例1:  
  139. Window = {}  
  140. Window.prototype = {x=0y=0width=100height=100}  
  141. Window.mt = {}  
  142. function Window.new(o)  
  143.     setmetatable(o, Window.mt)  
  144.     return o  
  145. end  
  146. WindowWindow.mt.__index = Window.prototype  
  147. WindowWindow.mt.__newindex = Window.prototype  
  148. w = Window.new{x=10y = 20}  
  149. print(w.width)             
  150.  
  151. w.width = 200 
  152. print(w.width)   
  153. print(Window.prototype.width)  
  154. 结果为:100 200 200  
  155.  
  156. 例2:  
  157. Window = {}  
  158. Window.prototype = {x=0y=0width=100height=100}  
  159. Window.mt = {}  
  160. function Window.new(o)  
  161.     setmetatable(o, Window.mt)  
  162.     return o  
  163. end  
  164. Window.mt.__index = function (t, k)  
  165.     return Window.prototype[k]  
  166. end  
  167. Window.mt.__newindex = function (t, k, v)  
  168.     if Window.prototype[k] ~= nil then  
  169.         Window.prototype[k] = v  
  170.     else  
  171.         rawset(t, k, v)  
  172.     end  
  173. end  
  174. w = Window.new{x=10y = 20}  
  175. print(w.width)  
  176. w.width = 200 
  177. print(w.width)