I said earlier that, when we access an absent field in a table, the result is nil. This is true, but it is not the whole truth. Actually, such access triggers the interpreter to look for an
__index
metamethod: If there is no such method, as usually happens, then the access results in nil; otherwise, the metamethod will provide the result.The archetypal example here is inheritance. Suppose we want to create several tables describing windows. Each table must describe several window parameters, such as position, size, color scheme, and the like. All these parameters have default values and so we want to build window objects giving only the non-default parameters. A first alternative is to provide a constructor that fills in the absent fields. A second alternative is to arrange for the new windows to inherit any absent field from a prototype window. First, we declare the prototype and a constructor function, which creates new windows sharing a metatable:
-- create a namespace Window = {} -- create the prototype with default values Window.prototype = {x=0, y=0, width=100, height=100, } -- create a metatable Window.mt = {} -- declare the constructor function function Window.new (o) setmetatable(o, Window.mt) return o endNow, we define the__index
metamethod:Window.mt.__index = function (table, key) return Window.prototype[key] endAfter that code, we create a new window and query it for an absent field:w = Window.new{x=10, y=20} print(w.width) --> 100When Lua detects thatw
does not have the requested field, but has a metatable with an__index
field, Lua calls this__index
metamethod, with argumentsw
(the table) and"width"
(the absent key). The metamethod then indexes the prototype with the given key and returns the result.The use of the
__index
metamethod for inheritance is so common that Lua provides a shortcut. Despite the name, the__index
metamethod does not need to be a function: It can be a table, instead. When it is a function, Lua calls it with the table and the absent key as its arguments. When it is a table, Lua redoes the access in that table. Therefore, in our previous example, we could declare__index
simply asWindow.mt.__index = Window.prototypeNow, when Lua looks for the metatable's__index
field, it finds the value ofWindow.prototype
, which is a table. Consequently, Lua repeats the access in this table, that is, it executes the equivalent ofWindow.prototype["width"]which gives the desired result.
lua的__index提供便利的单继承功能
最新推荐文章于 2024-09-11 22:08:39 发布