lua metatable, metamethod


lua metatable, metamethod

Lua official reference manual: https://www.runoob.com/manual/lua53doc/manual.html#2.4



1. Summary:

☺ 1. When an ordinary table cannot be found, or operations cannot be performed, consider setting the metamethod of the metatable on it.

2. The essence of metatable: In fact, metatable is essentially an ordinary table, it is just different from others in function! In fact, it is an ordinary table

3. The role of the metatable: defining the behavior of original values ​​under specific operations

4. Meta methods: In fact, they are some functions in the meta table



Two, meta table, meta method

1. The use of metatables, for example:

  • When tb is a table, if you add it directly, you will be wrong!
tb = {
    
    a = 1}
print(tb + 1)
  • As a result, an error will be reported: attempt to perform arithmetic on a table value (global 'tb')
  • Solution: We use the meta table, define it, and define a meta method __add
tb = {
    
    a = 1}
-- 新建一个元表(元表其实就是普通的表,只是功能和普通表不一样)
mt = {
    
    
	-- 元表中的元方法__add
	__add = function(a, b)
		return a.a + b
	end
}
-- 给tb这张表绑定上元表,这样普通表的加法就被替换成元表的__add 方法
setmetatable(tb, mt)
print(tb + 1)
  • result:

    2


2. The function setmetatable(table, metatable) to set the metatable for ordinary tables


3. The metatable determines the behavior of an object in mathematical operations, bit operations, comparisons, connections, length taking, calling, and indexing .

(1) Mathematical operations: addition, subtraction, multiplication, division, modulus, power, negation, rounding down, bitwise and, bitwise or, bitwise exclusive or, left shift, right shift

  • What follows is a detailed list of events that metatables can control. Each operation is distinguished by a corresponding event name. __The key name of each event is represented by a string prefixed with ' '; for example, the key name of the "add" operation is the string "_add".

__add: + operation. If any value that is not a number is added, Lua will try to call the metamethod.

For example, the following: tb is a table, not a number, and cannot be added directly. Lua will check whether the tb table is set with the metatable mt, and then check the metamethods in the metatable mt, and find that there are The existence of the addition __add metamethod, and then the addition metamethod is called.

tb = {
     
     a = 1}
print(tb + 1)

4. Important and special meta-method __index

(1) Function:

table[key], this event is triggered when the table is not a table or the key does not exist in the table. At this time, the corresponding meta-method of the table will be read.

(2) Example:

  • When there is no index b in table tb, tb[b] will eventually be nil
tb = {
    
    a = "hello"}
print(tb[b])
  • Solution: We set up the meta table for tb, then define the meta table and define a meta method __index, so that when the index cannot be found, the meta method will be called
tb = {
    
    a = "hello"}
--定义一个元表
mt = {
    
    
	--定义一个元方法__index
	__index = function(table, key)
		return "hi,boy"	
	end

}
-- 给tb这张表绑定上元表
setmetatable(tb, mt)
print(tb['b'])
  • Result: hi, boy

(3) __index details: The meta-method of this event can actually be a function or a table!

  • such as above
--定义一个元表
mt = {
    
    
	--定义一个元方法__index
	__index = {
    
    
        a = 10,
        b = 5,
    }
}
  • Result: print(tb['b']) returns 5
  • If print(tb['b']) returns hello, it can be found in the tb table. Only if it cannot be found, the metatable set on it will be considered.

5. Meta method __newindex

(1) Features: Triggered when assignment

Once you have the "__newindex" metamethod, Lua no longer does the initial assignment. (If necessary, the rawset method can be called inside the metamethod to do the assignment.)

  • For example: Lua’s original assignment method is as follows:
tb = {
    
    a = "hello"}
tb['b'] = 10
print(tb['b'])
  • The result is: 10

  • Set up a meta table for the tb table, and there is a meta method __newindex in the meta table

tb = {
    
    a = "hello"}
--定义一个元表
mt = {
    
    
	--定义一个元方法__newindex
	__newindex = function(t, k, v) --因为————newindex 会覆盖给原来的表进行赋值的操作,即覆盖操作tb['b'] = 10
	end
}
setmetatable(tb, mt)
tb['b'] = 10
print(tb['b'])
  • The result is: nil [Because the metatable is set on the table, and the metatable has the __newindex method, the original assignment method will not take effect]
  • Solution: You can call the rawset method inside the meta method to do the assignment.
tb = {
    
    a = "hello"}
--定义一个元表
mt = {
    
    
	--定义一个元方法__newindex
	__newindex = function(t, k, v)
		rawset(t,k,v) --发现,tb['b'] = 10 又可以正常赋值了
	end
}
setmetatable(tb, mt)
tb['b'] = 10
print(tb['b'])

(2) Why use rawset

  • Not using rawset may cause stack overflow


  • Reasons for using rawset: You can avoid triggering the meta method __index



Article reference:

Video at station B, author - Drink porridge every day "[Lua] metatable, metamethod, object-oriented" https://www.bilibili.com/video/BV1f44y1a7Gk/




If this article is helpful to you, please remember to give Yile a like, thank you!

Guess you like

Origin blog.csdn.net/weixin_45630258/article/details/130415489