MetaTable detailed in Lua _lua

Source: Internet
Author: User
Tags arithmetic arithmetic operators inheritance lua stdin

The metatable in Lua is a common table, but it has the following features:

1. Define the behavior of arithmetic operators and relational operators
2. Providing support for the LUA function library
3. Control access to table

Metatables defines operator behavior

MetaTable can be used to define the behavior of arithmetic operators and relational operators. For example, when Lua tries to add to two table, it checks whether there is an existing metatable in the two table sequentially and whether the metatable exists __add domain, and if LUA checks the __add domain, it is called, and the domain is called Metamethod.

Each value in Lua can have a metatable (in Lua 5 only table and UserData can exist metatable). Each table and UserData value has a metatable of its own, while all other types of each value share a metatable that belongs to this type. In the LUA code, the LUA C API can be set to all the metatable of value by invoking setmetatable to set and only set the table's metatable. By default, the string type has its own metatable, while the other types do not:

Copy Code code as follows:

Print (getmetatable (' Hi '))--> table:003c86b8
Print (Getmetatable ())--> Nil

The Metamethod parameters are operands (operands), for example:

Copy Code code as follows:

Local MT = {}
function Mt.__add (A, B)
Return ' table + '. B
Local T = {}
Setmetatable (T, MT)
Print (T + 1)

Each arithmetic operator has a corresponding Metamethod:

+ __add
* __mul
- __sub
/ __div
- __UNM (for negation)
% __mod
^ __pow

There is a corresponding metamethod:__concat for the join operator

Similarly, there are corresponding metamethod for relational operators:

== __eq
< __lt
<= __le

The other relational operators are represented in the above three ways:
A ~= B is expressed as not (a = = b)
A > B is represented as B < a
A >= b for B <= a

Unlike arithmetic operators, relational operators are used to compare two value with different metamethod (rather than metatable) with an error, with the exception of comparison operators, and the result of two value comparisons with different Metamethod is false.

Note, however, that a <= B can be converted to not (b < a) in a comparison of integer types, but this condition may not be true if all elements of a type are not sorted properly. For example: Nan (not a number) in a floating-point number represents an undefined value, Nan <= x is always false, and X < NaN is always false.

Support for the Lua function library

The LUA library can define and use Metamethod to perform certain operations, a typical example is the ToString function in the LUA base library (the print function calls this function for output) to check and invoke __tostring Metamethod:

Copy Code code as follows:

Local MT = {}
mt.__tostring = function (t)
Return ' {' ... table.concat (t, ', '). '}'

Local T = {1, 2, 3}
Print (t)
Setmetatable (T, MT)
Print (t)

Another example is the setmetatable and getmetatable functions, which define and use the __metatable domain. If you want to set the value of the metatable not be modified, then you can set the __metatable field in the metatable of value, Getmetatable will return this field, and setmetatable will produce an error:

Copy Code code as follows:

Mt.__metatable = "Not Your Business"
Local T = {}
Setmetatable (T, MT)
Print (getmetatable (t))--> not your business
Setmetatable (t, {})
Stdin:1: Cannot change protected metatable

Look at a complete example:

Copy Code code as follows:

Set = {}

Local MT = {}

function (l)
Local set = {}
--Set metatable for set
Setmetatable (set, MT)
For _, V. in Ipairs (L) does set[v] = True End
return set

function Set.union (A, B)
--Check whether a B is all Set
If Getmetatable (a) ~= MT or getmetatable (b) ~= Mt Then
--The second parameter of the error is level
--level specifies how to get the wrong location
--the level value of 1 indicates the location where the error function is called
--A level value of 2 indicates where the error is called where the function calling the error is invoked
Error ("Attempt to ' add ' a set with a Not-set value", 2)
Local res ={}
For k in pairs (a) does res[k] = True End
For k in pairs (b) does res[k] = True End
return res

function Set.intersection (A, B)
Local res ={}
For k in pairs (a) do
RES[K] = B[k]
return res

Mt.__add = Set.union
Mt.__mul = Set.intersection

Mt.__tostring = function (s)
Local L = {}
For e in pairs (s) do
l[#l + 1] = E
Return ' {' ... table.concat (l, ', '). '}'

Mt.__le = function (A, B)
For k in pairs (a) do
If not b[k] then return False end
return True

Mt.__lt = function (A, B)
Return a <= B and not (b <= a)

Mt.__eq = function (A, B)
Return a <= B and B <= a

Local S1 = ({1, 2, 3})
Local S2 = ({4, 5, 6})
Print (S1 + s2)
Print (S1 ~= S2)

Control access to table

__index Metamethod

When we access the nonexistent domain of the table, Lua attempts to invoke __index Metamethod. __index Metamethod accepts two parameters table and key:

Copy Code code as follows:

Local MT = {}
Mt.__index = function (table, key)
Print (' Table--'.. tostring (table))
Print (' Key--' ... key ')

Local T = {}
Setmetatable (T, MT)
Local v = t.a

__index field can also be a table, Lua will try to access the corresponding domain in __index table:

Copy Code code as follows:

Local MT = {}
Mt.__index = {
A = ' Hello world '

Local T = {}
Setmetatable (T, MT)
Print (T.A)--> Hello World

We can easily implement single inheritance through __index (similar to javascrpit through prototype implementation of single inheritance), if __index is a function, you can achieve more complex functions: multiple inheritance, caching and so on. We can access the domain I of table t via Rawget (T, i) without accessing the __index Metamethod, and note that you don't expect to increase access to the table by Rawget (in Lua, the call overhead for functions is much greater than the access to the table. Pins).

__newindex Metamethod

If you assign a value to a nonexistent field in a table, Lua checks for __newindex Metamethod:

1. If __newindex is a function, Lua calls the function instead of assigning it
2. If __newindex is a table,lua, this table will be assigned a value

If __newindex is a function, it can accept three parameter table key value. If you want to ignore the __newindex method to assign values to the table's fields, you can call Rawset (t, K, V)

Combined with __index and __newindex, many functions can be implemented, such as:

1.OOP table
3.Tables with default values

Read-only table

Copy Code code as follows:

function ReadOnly (t)
Local proxy = {}
Local MT = {
__index = T,
__newindex = function (t, K, V)
Error (' Attempt to update a read-only table ', 2)
Setmetatable (proxy, MT)
Return proxy

Days = readonly{' Sun ', ' Mon ', ' Tues ', ' Wed ', ' Thur ', ' Fri ', ' Sat '}
Print (Days[1])
DAYS[2] = ' Noday '--> stdin:1: Attempt to update a read-only table

Sometimes, we need to set a unique key for the table, so we can use this technique:

Copy Code code as follows:

Local key = {}--Unique key
Local T = {}
T[key] = value

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.