Lua高次メタテーブル

4293 ワード

メタテーブル
Lua 5.1言語では、メタテーブル(metatable)の表現動作は、C++言語のオペレータリロードと同様であり、例えば、2つのLua配列の並列セットを計算するために「_add」メタメソッド(metamethod)をリロードすることができる.あるいは「_index」メソッドを再ロードして、独自のHash関数を定義します.Luaは、次のようにメタテーブルを処理するために非常に重要な2つの方法を提供します.
  • setmetatable(table,metatable):このメソッドは、テーブルにメタテーブルを設定するために使用されます.
  • getmetatable(table):このメソッドは、テーブルのメタテーブルオブジェクトを取得するために使用されます.

  • メタテーブルを設定する方法は簡単です.次のようにします.
    local mytalbe = {}
    local mymetatable = {}
    setmetatable(mytable, mymetatable)
    

    上のコードは次のように簡単に書くことができます.
    local mytable = setmetatable({}, {})
    

    テーブルのオペレータ動作の変更
    「_add」メタメソッドを変更して、コアの並列セットインスタンスを計算します.
    local set1 = {10, 20, 30}   --   
    local set2 = {20, 40, 50}   --   
    
    --      __add   ,        self
    local union = function (self, another)
      local set = {}
      local result = {}
      
      --              
      for i, j in pairs(self) do set[j] = true end
      for i, j in pairs(another) do set[j]= true end
      
      --       
      for i, j in pairs(set) do table.insert(result, i) end
      return result
    end
    
    setmetatable(set1, {__add = union}) --   set1  __add   
    
    local set3 = set1 + set2
    for _, j in pairs(set3) do
      io.write(j.." ")      -- output: 30 50 20 40 10
    end
    

    加算を再ロードできるほか、Luaが提供するすべてのオペレータを再ロードできます.
    メタメソッド
    意味
    "__add"
    +アクション
    "_sub"
    -アクション「add」アクションと同様の動作
    "__mul"
    *アクション「add」アクションと同様の動作
    "__div"
    /アクション「add」アクションと同様の動作
    "__mod"
    %アクション「add」アクションと同様の動作
    "__pow"
    ^(べき乗)アクションaddアクションと同様の動作
    "__unm"
    単元-アクション
    "__concat"
    ..(文字列接続)アクション
    "__len"
    #アクション
    "__eq"
    ==操作関数getcompandlerはluaがどのように1つのプロセッサを選択して比較操作を行うかを定義し、2つのオブジェクトタイプが同じで、対応する操作が同じメタメソッドがある場合にのみ有効です.
    "__lt"
    "__le"
    <=操作
    オペレータに加えて、次のメタメソッドをリロードすることもできます.次に、使用方法を順次説明します.
    メタメソッド
    意味
    "__index"
    table[key]にアクセスするには、ラベルを外す操作を使用します.
    "__newindex"
    指定した下付きタブに値を割り当てる[key]=value
    "__tostring"
    文字列に変換
    "__call"
    Luaが値を呼び出すと呼び出されます
    "__mode"
    弱表用(week table)
    "__metatable"
    metatableをアクセスから保護するために使用
    __indexメタメソッド
    次の例では、テーブルにキーが存在しない場合にメタテーブルでキーを検索する機能を実現します.
    mytable = setmetatable({key1 = "value1"},   --   
        {__index = function(self, key)          --    
            if key == "key2" then
                return "metatablevalue"
            end
        end
      })
    
    print(mytable.key1, mytable.key2) -- output: value1 metatablevalue
    

    についてindexメタメソッドには、比較的高いテクニックがたくさんあります.例えば、_indexのメタメソッドは、関数でなくてもテーブルであってもよい.
    t = setmetatable({[1] = "hello"}, {__index = {[2] = "world"}})
    print(t[1], t[2]) -- output: hello world
    

    まず{_index={}}をメタテーブルとするが_indexは関数ではなくテーブルを受け入れ、このテーブルには[2]=「world」というキー値ペアが含まれています.だからt[2]が自分の表に見つからないとき、_indexのテーブルを探して、[2]=「world」というキー値のペアを見つけました.+
    __indexメタメソッドは、テーブル内の各値にデフォルト値を割り当てることもできます.および_newindexメタメソッドは,テーブルの読み取り,修正などの比較的高い機能を共同で監視し,読者自身が開発するのを待つ.
    __tostringメタメソッド
    JavaのtoString()関数と同様に、カスタム文字列変換を実現できます.
    arr = {1, 2, 3, 4}
    arr = setmetatable(arr, {__tostring = function (self)
        local result = '{'
        local sep = ''
        for _, i in pairs(self) do
          result = result .. sep .. i
          sep=', '
        end
        result = result .. '}'
        return result
    end})
    
    print(arr) --> {1, 2, 3, 4}
    

    __callメタメソッド
    __callメタメソッドの機能はC++の擬似関数に類似しており,通常のテーブルも呼び出すことができる.
    functor = {}
    function func1(self, arg)
      print ("called from", arg)
    end
    
    setmetatable(functor, {__call = func1})
    
    functor("functor") --> called from functor
    print(functor) --> output:0x00076fc8 (           )
    

    __metatableメタメソッド
    もし私たちがオブジェクトを保護したいなら、使用者が見えないようにmetatablesを変更することはできません.metatableを設定できます.metatableの値、getmetatableはこのドメインの値を返し、setmetatableを呼び出すとエラーが発生します.
    Object = setmetatable({}, {__metatable = "You cannot access here"})
    
    print(getmetatable(Object)) --> You cannot access here
    setmetatable(Object, {})    -->        
    

    記事の転載先:https://moonbingbing.gitbooks.io/openresty-best-practices/content/lua/metatable.html