この初版は Lua 5.0 向けに執筆されました。依然として後のバージョンでも大部分が関連性がありますが、相違点があります。
第 4 版は Lua 5.3 版を対象にしており、Amazon やその他の書店で購入できます。
本を購入することで、Lua プロジェクトを支援することもできます。
![]() |
プログラミングLua | ![]() |
第 II 部. テーブルとオブジェクト 第 13 章. メタテーブルとメタメソッド |
__index
メタメソッドテーブル内の欠落したフィールドにアクセスすると結果は nil になると前述しました。これは事実ですが、すべてではありません。実際、こうしたアクセスによって、インタプリタは __index
メタメソッドの検索がトリガされます。通常どおりそのようなメソッドがなければ、アクセス結果は nil になります。それ以外の場合は、メタメソッドが結果を提供します。
典型的な例は継承です。ウィンドウを説明する複数のテーブルを作成したいとします。それぞれのテーブルは、位置、大きさ、配色などのいくつかのウィンドウ パラメータを説明している必要があります。こうしたすべてのパラメータには既定値があるため、既定値以外のウィンドウ オブジェクトを作成してパラメータを提供する必要があります。最初の選択肢は、欠落したフィールドを埋めるコンストラクタを提供することです。2 番目の選択肢は、新しいウィンドウに対してプロトタイプ ウィンドウからどの欠落したフィールドでも 継承 できるようにすることです。まず、プロトタイプと、メタテーブルを共有する新しいウィンドウを作成するコンストラクタ関数を宣言します
-- 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次に、
__index
メタメソッドを定義しますWindow.mt.__index = function (table, key) return Window.prototype[key] endこのコードの後で、新しいウィンドウを作成し、欠落したフィールドをクエリします
w = Window.new{x=10, y=20} print(w.width) --> 100Lua が
w
に要求したフィールドがないものの、__index
フィールドがあるメタテーブルがあることを検出すると、Lua はこの __index
メタメソッドを、引数 w
(テーブル) と "width"
(欠落したキー) を使用して呼び出します。このメタメソッドにより、プロトタイプは指定されたキーでインデックスが作成され、結果が返されます。継承の __index
メタメソッドの使用方法は一般的であるため、Lua はショートカットを提供しています。名前にもかかわらず、__index
メタメソッドは関数の必要はありません。その代わりにテーブルになることもできます。それが関数である場合、Lua はそれらをテーブルと、その引数として欠落したキーを呼び出します。それがテーブルである場合、Lua はそのテーブルにアクセスし直します。したがって、前の例では __index
を単に以下のように宣言できます
Window.mt.__index = Window.prototypeこの時点で、Lua がメタテーブルの
__index
フィールドを探す時、その値が Window.prototype
のテーブルであることを検出します。その結果、Lua はこのテーブルへのアクセスを繰り返します。つまり、以下と同等の操作を行います。Window.prototype["width"]これは目的の結果を提供します。
テーブルを __index
メタメソッドとして使用すると、単一継承を実装するための安価でシンプルな方法になります。関数はコストは高くなりますが、より多くの柔軟性を提供します。多重継承、キャッシング、その他多くのバリエーションを実装できます。これらの継承形式については 第 16 章 で説明します。
__index
メタメソッドを呼び出さずにテーブルにアクセスする場合は、rawget
関数を使用します。rawget(t,i)
の呼び出しはテーブル t
へのローアクセスを行います。ローアクセスを行うことでコードが高速化することはありません(関数呼び出しのオーバーヘッドにより、得られる利得はすべてなくなります)。しかし、後述するように、場合によっては必要な場合があります。
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. | ![]() |