- metatables and metamethods
- getmetatable(t)
- setmetatable(t, tm)
- 1, 算术运算
- __add, __mul, __sub, __div,__unm(负数), __pow(幂)
- lua选择metamethod的原则:(第一个参数)or (第二个参数)
- 意思是,第一个参数存在__add则用第一个参数,如果第一个参数不存在__add,则用第二个参数的,
- 如果第二个参数不存在则报错;
- 例:
- Set = {}
- Set.mt = {} --metatable
- function Set.union(a, b) --metamethod
- local res = Set.new{}
- for k in pairs(a) do res[k] = true end
- for k in pairs(b) do res[k] = true end
- return res
- end
- function Set.tostring(set)
- local s = "{"
- local sep = ""
- for e in pairs(set) do
- ss = s..sep..e
- sep = ","
- end
- return s.."}"
- end
- function Set.print(s)
- print(Set.tostring(s))
- end
- function Set.new(t)
- local set = {}
- setmetatable(set, Set.mt) --set metatable
- SetSet.mt.__add = Set.union --set metamethod
- for _, l in ipairs(t) do set[l] = true end
- return set
- end
- a = Set.new{1, 3, 5, 7, 9}
- b = Set.new{2, 4, 6, 8, 0}
- s = a + b
- Set.print(s)
- 2, 关系运算符
- __eq(等于), __lt(小于), __le(小于等于)
- 3, 关系运算符号与算术运算符号,当遇到不支持的类型时候,都抛出异常
- 但等号运算不会抛出异常
- 4, __tostring, 串格式化(print 函数总是调用tostring来格式化它的输出,而tostring总是检查__tostring域)
- Set = {}
- Set.mt = {}
- function Set.union(a, b)
- local res = Set.new{}
- for k in pairs(a) do res[k] = true end
- for k in pairs(b) do res[k] = true end
- return res
- end
- function Set.tostring(set)
- local s = "{"
- local sep = ""
- for e in pairs(set) do
- ss = s..sep..e
- sep = ","
- end
- return s.."}"
- end
- function Set.new(t)
- local set = {}
- setmetatable(set, Set.mt)
- SetSet.mt.__add = Set.union
- SetSet.mt.__tostring = Set.tostring
- for _, l in ipairs(t) do set[l] = true end
- return set
- end
- a = Set.new{1, 3, 5, 7, 9}
- b = Set.new{2, 4, 6, 8, 0}
- s = a + b
- print(s)
- 5, __metatable, 如果设置了这个域
- 则getmetatable将返回这个值,而setmetatable将报错
- 6,
- Set = {}
- Set.mt = {}
- Set.mt.__metatable = "no no no"
- setmetatable(Set, Set.mt)
- print(getmetatable(Set)) --结果为"no no no"
- setmetatable(Set, {}) --会报错
- 7,__index
- 当我们访问一个表的不存在的域的时候,访问会触发lua解析器去查找__index方法, 如果不存在则返回nil
- 否则则将这个table和它缺少的域为参数调用__index函数
- 如果__index的为一个表,则直接在这个表中查找缺少值
- 例1:
- Window = {}
- Window.prototype = {x=0, y=0, width=100, height=100}
- Window.mt = {}
- function Window.new(o)
- setmetatable(o, Window.mt)
- return o
- end
- Window.mt.__index = function (table, key)
- return Window.prototype[key]
- end
- w = Window.new{x=10, y = 20}
- print(w.width)
- 例2:
- Window = {}
- Window.prototype = {x=0, y=0, width=100, height=100}
- Window.mt = {}
- function Window.new(o)
- setmetatable(o, Window.mt)
- return o
- end
- WindowWindow.mt.__index = Window.prototype
- w = Window.new{x=10, y = 20}
- print(w.width)
- 8, __newindex
- 当你给表的一个缺少的域赋值,解释就会查找__newindex,如果__newindex是一个函数,
- 如果存在则调用这个函数而不是赋值操作,
- 当你给表的一个缺少的域赋值,如果__newindex是一个表,则对这个表进行赋值,而不是对原表进行赋值
- rawset(t, k, v) 不会查找__newindex
- rawget(t,k) 不会查找__index
- 例1:
- Window = {}
- Window.prototype = {x=0, y=0, width=100, height=100}
- Window.mt = {}
- function Window.new(o)
- setmetatable(o, Window.mt)
- return o
- end
- WindowWindow.mt.__index = Window.prototype
- WindowWindow.mt.__newindex = Window.prototype
- w = Window.new{x=10, y = 20}
- print(w.width)
- w.width = 200
- print(w.width)
- print(Window.prototype.width)
- 结果为:100 200 200
- 例2:
- Window = {}
- Window.prototype = {x=0, y=0, width=100, height=100}
- Window.mt = {}
- function Window.new(o)
- setmetatable(o, Window.mt)
- return o
- end
- Window.mt.__index = function (t, k)
- return Window.prototype[k]
- end
- Window.mt.__newindex = function (t, k, v)
- if Window.prototype[k] ~= nil then
- Window.prototype[k] = v
- else
- rawset(t, k, v)
- end
- end
- w = Window.new{x=10, y = 20}
- print(w.width)
- w.width = 200
- print(w.width)