__index = function (table, key)

本文介绍Lua中如何使用元表实现继承,通过__index元方法让表继承另一个表的属性。展示了如何定义原型表及构造函数,并利用__index元方法实现默认属性的继承。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

his first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The third edition targets Lua 5.2 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.


13.4.1 – The __index Metamethod

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
    end
Now, we define the  __index  metamethod:
    Window.mt.__index = function (table, key)
      return Window.prototype[key]
    end
After that code, we create a new window and query it for an absent field:
    w = Window.new{x=10, y=20}
    print(w.width)    --> 100
When Lua detects that  w  does not have the requested field, but has a meta table  with an  __index  field, Lua calls this  __index  metamethod, with arguments  w  (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 as

    Window.mt.__index = Window.prototype
Now, when Lua looks for the meta table 's  __index  field, it finds the value of  Window.prototype , which is a  table . Consequently, Lua repeats the access in this  table , that is, it executes the equivalent of
    Window.prototype["width"]
which gives the desired result.

The use of a table as an __index metamethod provides a cheap and simple way of implementing single inheritance. A function, although more expensive, provides more flexibility: We can implement multiple inheritance, caching, and several other variations. We will discuss those forms of inheritance in Chapter 16.

When we want to access a table without invoking its __index metamethod, we use the rawget function. The call rawget(t,i) does a raw access to table t. Doing a raw access will not speed up your code (the overhead of a function call kills any gain you could have), but sometimes you need it, as we will see later.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值