luaメタテーブルとオブジェクト向け

3329 ワード

メタテーブル
まずluaのnumberタイプは、例えば、いくつかの操作を実行することができる.
1 + 1 //2
1 - 1 //0

2つの複素数を以下のように定義すれば,その加算を実現することが望ましい.
local a = {1, 2}
local b = {3, 4}
//          {4, 6}

この2つの変数を直接加算すると、lua解釈器はエラーを教えてくれます.このとき,メタテーブルによって所望の結果を達成することができ,メタテーブルはメタ操作または挙動の集合として理解できる.任意の変数のメタテーブルは、setmetatableによって設定されたtableのメタテーブルgetmetatableによって取得することができる.新しいtableが作成されるとメタテーブルが空になります.
式a+bは、Luaでは以下の手順で行われる
  • まず、aとbの両方がメタテーブル
  • を有するか否かを判断する.
  • メタテーブルに__という名前があるかどうかを確認します.addのフィールド;フィールドが見つかった場合は、フィールドに対応する値を呼び出します.この値はメソッドに対応します.

  • Luaでは、各値に1つのメタテーブルがあり、tableタイプとuserdataタイプの各変数にはそれぞれ独立したメタテーブルがあり、他のタイプの値はそのタイプが属する単一のメタテーブルを共有します.
    local m = {
        __add = function (a, b)
            return {a[1] + b[1], a[2] + b[2]}
        end
    }
    local a = setmetatable({1,2}, m)
    local b = setmetatable({3,4}, m)
    //   a + b        {4, 6}
    

    加算に加えて、メタテーブルには次のような操作があります.
    Mode
    説明
    __add
    プラス
    __sub
    減らす
    __mul
    乗ずる
    __div
    を除いて
    __mod
    余剰を取る
    __unm
    逆数をとる
    __concat
    せつぞく
    __eq
    に等しい
    __lt
    より小さい
    __le
    以下
    __call
    メソッドとしてtableを呼び出すとメタテーブルの__が呼び出されます.call
    __tostring
    tableをstringとして入力するとメタテーブルの__が呼び出されます.tostring
    __index
    以下に述べる
    __newindex
    以下に述べる
    __indexメタメソッド
    tableのフィールドにアクセスすると、tableにこのフィールドがある場合は、対応する値を直接返します.tableにこのフィールドがない場合、tableのメタテーブルの__を探します.index、nilを返すのが見つかりませんでした.もしあるならば2種類の情況に分けて、_indexは方法でもtableでもよい.
    メソッドの場合、tableとkeyがこのメソッドを呼び出し、結果は次のようになります.
    local m = {
        __index = function(table, key)
            return key .. key
        end
    }
    
    local t = {}
    setmetatable(t, m)
    //    t.a == 'aa', t.abc == 'abcabc'
    

    tableであれば、このtableに対応するkeyを探し、見つけたら返し、見つからなければこのtableのメタテーブルを探し続ける_.index、つまりずっと上を探しています.
    local a = {}
    local b = {a = 1}
    local c = {b = 2}
    setmetatable(a, {__index = b})
    setmetatable(b, {__index = c})
    // a.a == 1
    // a.b == 2
    

    __newindexメタメソッド
    この方法はtableのkeyを更新するときに呼び出され,すなわちtableのkeyに値を付与するときである.主な役割は
    local a = {}
    setmetatable(a, {
        __newindex = function(table, key, value) 
        print(key)
        print(value)
        end
    })
    a.a = 10
    //      a 10
    

    オブジェクト向け
    上のメタテーブルの基礎があればluaのオブジェクト向けを実現できます.オブジェクトを作成するときにメタメソッドの__としてtableをクラスとして定義します.index、luaのselfキーワードを再使用
    local People = {
        name = ''
    }
    
    function People:say()
        print(self.name)
    end
    
    function People:new(name)
        local o = {name = name}
        setmetatable(o, {__index = self})
        
        return o
    end
    
    local xiaoming = People:new('xiaoming')
    xiaoming:say() //     xiaoming
    

    次は継承
    local People = {
        name = ''
    }
    
    function People:say()
        print(self.name)
    end
    
    function People:new(name)
        local o = {name = name}
        setmetatable(o, {__index = self})
    
        return o
    end
    
    local Teacher = {
    }
    function Teacher:say()
        print('teacher ' .. self.name)
    end
    setmetatable(Teacher, {__index = People})
    
    local xiaoming = Teacher:new('xiaoming')
    xiaoming:say() //     teacher xiaoming
    

    もちろん,クラスとオブジェクトと継承を実現する方法には他にも多くの種類があり,上はその原理を例示しているだけである.クラスを定義し、親クラスに転送し、オブジェクト向けをより容易に実現するためにclassメソッドをカプセル化できます.ここでは詳しくは述べない.関連キーワードを直接検索すればいいです.