3

標準のメタテーブル メソッドの代わりに、関数型の方法で lua でオブジェクト指向プログラミングを行う方法を発見 (および作成) しました。はるかに多くの機能を備えています (しゃれは意図していません) が、パフォーマンスが低下する可能性があるのではないかと心配しています。私の目標は、lua で記述されたサーバーで実験することであり、この OOP ソリューションを使用したいと考えていました。とにかく、ここに新しいオブジェクトとサブクラスを作成するための関数を保持する私のclass.luaがあります。

local classes = setmetatable({}, {__mode = "k"}) -- Allow the GC to empty this as needed.

function class(f, super)
    classes[f] = {super = super}
end

function new(f, obj, ...)
    local fenv = getfenv(f)
    if type(obj) ~= "table" then
        error("bad argument: expected table, got " .. type(obj) , 2)
    end

    if classes[f] and classes[f].super then
        new(classes[f].super, obj, ...)
        local super = obj
        obj = setmetatable({}, { __index = super })
        obj.super = super
    else
        setmetatable(obj,{__index = fenv})
    end

    obj.this = obj
    setfenv(f, obj)
    f()
    setfenv(f, fenv)

    if obj.init then
        obj.init( ... )
    end

    return obj
end

使い方はかなり簡単です。次の例を見てください。

function Person()
    local privateVar = math.random()
    age, name, gender = nil, nil, nil

    function init(age, name, gender)
        this.age = age
        this.name = name
        this.gender = gender
    end

    function getAge()
        return age
    end

    function getName()
        return name
    end

    function getGender()
        return gender
    end

    function getPrivateVar()
        return privateVar
    end
end

そして、オブジェクトを作成するには

obj = new(Person, {}, "John", 30, "male")

サブクラス化も簡単

function Female()
    function init(name, age)
        super.init(name, age, "female")
    end
end

class(Female, Person)

サブクラス化したい場合は、関数を呼び出して何かをクラスにするだけでよいことに注意してください。

new を呼び出すときは、クラス、オブジェクト、および引数を渡します。オブジェクトのメタテーブルは、クラスの元の環境のインデックスを持つように設定されています。次に、スーパーが決定され、作成されます。次に、クラス関数が実行されて、すべてのインスタンス値が作成されます。次に、init が呼び出されます。

メタテーブルに対するこれの利点の 1 つは、他のコードがクラスを変更できず、そのクラスの既存および今後存在するすべてのインスタンスを変更できないことです。現在、そのようなことを行う唯一の方法は、クラスへのすべての参照がハッカーのダミー クラスを参照していることを確認するために、環境をスウィズルしてハックすることです。

その上、プライベート変数をサポートしています。クラス関数でローカルに宣言するだけで、準備完了です。

しかし、インスタンス化ごとにすべてのインスタンス メソッドを 1 回作成するという事実が、パフォーマンスの問題を引き起こすのではないかと考えています。これはメモリを食べますか?ここで何が問題になる可能性がありますか?

また、問題があります。これは多重継承をサポートしていますが、スーパー メソッドを呼び出し、スーパーがメソッドを呼び出すと、インスタンス化されたクラスではなく、スーパー クラスのメソッドが呼び出されます。インスタンス化されたクラスから呼び出す方法はありますか?

4

0 に答える 0