Luaノート--メタテーブルとメタメソッド

2848 ワード

メタテーブルを使用して、値の動作を変更し、事前定義されていない操作に直面したときに指定された操作を実行できます.Luaが2つのtableを加算しようとすると、両方のいずれかにメタテーブルがあるかどうかを確認し、元のテーブルに__という名前があるかどうかを確認します.addのフィールド.
Luaは新しいtableを作成するときにメタテーブルを作成しません.setmetatableを使用してtableのメタテーブルを設定または変更できます.
Luaではtableのメタテーブルしか設定できませんが、他のタイプの値のメタテーブルを設定するにはCコードで行う必要があります.その他のタイプは、デフォルトではメタテーブルがありません.
1、算術類のメタメソッド
Set = {}
local mt = {}
--                 
function Set.new( l )
	local set = {}
	setmetatable(set, mt)		-- mt        table   
	for _, v in ipairs(l) do set[v] = true end
	return set 
end
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.intersection( a, b )
	local res = Set.new{}
	for k in pairs(a) do res[k] = b[k] end 
	return res 
end
function Set.tostring( set )
	local l = {}
	for e in pairs(set) do l[#l + 1] = e end 
	return "{" ..table.concat(l, ", ") .. "}"		
	--table.concat                   ,       
end
function Set.print( s )
	print(Set.tostring(s))
end
s1 = Set.new{1, 2, 3, 4}
s2 = Set.new{2, 5}
--             
print(getmetatable(s1))		-->table: 0x7fee11c09940
print(getmetatable(s2))		-->table: 0x7fee11c09940
--         。
mt.__add = Set.union 
-- Lua          ,    Set.union  ,             
s3 = s1 + s2
Set.print(s3)		-->{1, 2, 3, 4, 5}
--   ,              
mt.__mul = Set.intersection 
Set.print((s1 + s2) * s1)		-->{1, 2, 3, 4}
--[[
    ,               。  __add  __mul ,  __sub(  )、
__div(  )、__unm(   )、__mod(  )、__pow(  )。  ,     __concat
  ,            。
]]

2、関係類のメタメソッド
mt.__le = function ( a, b )		--    
	for k in pairs(a) do
		if not b[k] then return false end 
	end 
	return true
end
mt.__lt = function ( a, b )
	return a <= b and not (b <= a)
end
mt.__eq = function ( a, b )
	return a <= b and b <= a 
end
s1 = Set.new{2, 4}
s2 = Set.new{2, 4, 8}
print(s1 <= s2)		-->true
print(s1 < s2)		-->true
print(s1 >= s2)		-->false
print(s1 > s2)		-->false
print(s1 == s2 * s1)		-->true

3、tableアクセスのメタメソッド
--[[     table        ,            __index    。
         ,       nil,                。
]]
Window = {}		--        
--            
Window.prototype = {x=0, y=0, width=100, height=200}
Window.mt = {}		--     
--      
function Window.new( o )
	setmetatable(o, Window.mt)
	return o
end
--  __index   
Window.mt.__index = function ( table, key )
	return Window.prototype[key]
end
--__index       ,      table
--Window.mt.__index = Window.prototype
--       ,           
w = Window.new{x = 10, y = 20}
print(w.width)		-->100

        __newindexメタメソッドと_indexメタメソッドは、前者はtableの更新に使用され、後者はtableのクエリーに使用される点で同様である.1つのtableに存在しないインデックスに値を割り当てると、解釈器は__を検索します.newindexメタメソッド.このメタメソッドがある場合、解釈器は割り当てを実行するのではなく、それを呼び出します.