Multiple inheritance implementation in Lua

said before in Implementing Object Orientation in Lua , Today we will talk about multiple inheritance in detail

inherit

Any method inherited from the base class can be redefined. Just write a new method.
An interesting property of objects in Lua is that there is no need to create a new class in order to specify a new behavior.

multiple inheritance

1. Multiple inheritance to find a field in multiple classes

In fact, there is nothing special about multiple inheritance, unless the two classes to be inherited have the same function names and properties, otherwise, it is very simple to deal with.

It's nothing more than finding a field in multiple table s, isn't it simple? Inheritance in Lua is to find fields that do not exist in other people's table s.

Then, the difference between single inheritance and multiple inheritance is also here, one is to find only one table, and the other is to find two or more tables.

Let's first take a look at how to find a field from 2 or more table s, the following code:

function search(classes, key)
    for i = 1, #classes do
        local value = classes[i][key];
        if value ~= nil then
            return value;
        end
    end
end
local t1 = {name = "hehe"};
local t2 = {game = "who"};
print(search({t1, t2}, "game"));

The classes parameter here is a table, and this table stores multiple tables, that is, the classes we want to inherit.

The key is the field to look for.

Just traverse all the tables, determine whether the field is in a certain table, and return this value after finding it.

Our test code is to find the game field from t1 and t2. T1 and t1 can be regarded as two classes.

The output is as follows:

[LUA-print] who

2. Multiple inheritance creates subclasses that inherit multiple classes

code show as below

function createClass(...)
    local parents = {...};
    local child = {};

    -- set metatable for classes
    setmetatable(child, {
        __index = function(table, key)
            return search(parents, key);
        end
    })

    -- add a class new function to create an object
    function child:new()
        o = {};
        setmetatable(o, child);
        child.__index = child;
        return o;
    end

    -- Returns this subclass that inherits from multiple classes
    return child;
end

The createClass function is used to create a subclass that inherits multiple classes. It is a little complicated and will be analyzed slowly:

1) The parameter is a variable parameter, we need to pass in multiple inherited classes as parameters

2) parents are used to save these inherited classes

3) Create a new table-child, which is the subclass we want that inherits multiple classes

4) Set the metatable for the child, and set the __index metamethod. The __index metamethod can be a function. When it is a function, its parameters are the table to which the metatable belongs and the field name to be searched.

5) We call the search function in the __index metamethod function to find the required fields from multiple parent classes. Therefore, when a function of child is called, it will be searched from each parent class, which has completed the work of inheritance.

6) Next is the new function we are familiar with, which is used to create a subclass of child.

7) Finally return to child, everything is done.

It seems very complicated, but it is actually an application of __index.

Let's test it now, the following code:

    --a sprite class
    TSprite = {}
    function TSprite:hello()
        print("who are you hello!");
    end

    function TSprite:new()
        o = {}
        setmetatable(o, self);
        self.__index = self;
        return o;
    end

    -- a bullet class
    TBullet = {}
    function TBullet:fire()
        print("Don't move, I won't be able to aim anymore!");
    end

    function TBullet:new()
        o = {}
        setmetatable(o, self);
        self.__index = self;
        return o;
    end

    -- A subclass that inherits from both classes
    local BulletSprite = createClass(TSprite, TBullet);

    -- object of subclass
    local bSprite = BulletSprite:new();
    bSprite:hello();
    bSprite:fire();

Two classes are created here: TSprite and TBullet.

Then call the createClass function to create a subclass that inherits TSprite and TBullet.

Finally, create an object of the subclass and call the object's hello and fire functions.

The output is as follows:

[LUA-print] who are you hello!
[LUA-print] Don't move, I won't be able to aim anymore!

Summarize

  • Method 1, let the __index field become a function, and search for the method segments of multiple base classes in this function. The search has a certain complexity, and the performance is not as good as single inheritance

  • Method 2, copy the inherited method to the subclass, the disadvantage is that it is difficult to modify the definition of the method after the system is running.

  • The second implementation method is recommended, and the second method has been used in the project

Tags: OOP lua

Posted by seriousdamage on Thu, 05 May 2022 12:08:02 +0300