Both __index and __newindex play a role when there is no index of the required access in the table.
Therefore, it is possible to catch all access to a table only if it is kept empty. To monitor all access to a table, you should create a proxy for the real table.
This proxy is an empty table, where the __index and __newindex meta methods can be used to track all accesses and redirect access to the original table.
Suppose we want to track the access of table T, we can do this:
t = {}--original table, created in other placesLocal _t= T--maintain a private access to the original tablet = {}--Create a proxyLocalMT ={__index=function(t,k)Print("*access to Elemet"..ToString(k))return _tK--Access K in the original table End__newindex=function(t,k,v)Print("*update of Element"..ToString(k).." to"..ToString(v))_t[K] = V--Update the value of the original table End}setmetatable(T,MT)--To set MT as a meta-table of T
This code tracks all access to table T:
t[2"hello" -- *update of element 2 to Helloprint (t[2]) --> Hello --*access to Element 2
But the above example has a problem with the inability to traverse the original table. The function pairs can only manipulate the proxy table and cannot access the original table.
You can iterate by defining __pairs:
function () returnfunction(_,k) returnnext(_t , K) End End
If you want to monitor several tables at the same time, you do not need to create a different meta table for each table. Instead, whenever you associate each agent with its original table in some form,
And all agents share a common meta-table. This is similar to the issue discussed in the previous section that associates table with its default value.
For example, save the original table in a special field in the Agent table, as follows:
Localindex = {}--Create a private indexLocalMt = {--Create a meta table__index =function(t,k)Print("*access to Element"..ToString(k)returnT[INDEX][K]--access the original table End__newindex=function(t,k,v)Print("*update of Element"..ToString(k).." to"..ToString(v)) T[index][k]= V--Update the original table End__pairs=function(t)return function(t,k)return Next(t[index],k)End, TEnd}functionTrack (t)Localproxy={} Proxy[index]=Tsetmetatable(PROXY,MT)returnProxyEnd
Now, to monitor the table T, the only thing to do is execute:
t = Track (t)
Read-only table
Through the concept of proxies, it is easy to implement a read-only table, simply track all the new operations on the table and raise an error.
Because you do not have to trace query access, you can use the original table instead of the function for the __index meta method. This is also simpler and more efficient when redirecting all queries to the original table.
However, this practice requires that a new meta-table be created for each read-only agent, where __index points to the original table.
functionreadOnly (t)LocalProxy = {} LocalMT ={__index=T, __newindex=function(t,k,v)Error("*attempt to update a read-only table",2) End } setmetatable(PROXY,MT)returnProxyEnd
Here is an example of a use that creates a read-only table that represents the week:
Days = readonly{"Sunday","Monday","Tuesday","Thursday","Friday","Saturday"}Print(days[1])-->sundaydays[2] ="Noday" --> Stdin:1: Attempt to update a read-only table
The above: The second edition of LUA programming and the programming in Lua Third edition
Chapter 13_4 Tracking Table Access