Lua OOP. Как наследовать таблицы от прототипа - PullRequest
1 голос
/ 02 апреля 2020

В Программирование в Lua Я нашел пример для работы с наследованием. Я понял, как он обрабатывается с помощью метатаблицы __index, но когда я сделал свой собственный пример, где один из элементов, который должен наследоваться, - это таблица, я понял, что таблица используется совместно созданными объектами:

Account = {
    balance = 0,
    info = {},
    withdraw = function (self, v)
        self.balance = self.balance - v
    end,
    deposit = function (self, v)
        self.balance = self.balance + v
    end,
    add = function (self, item)
        if self:check(item) then return end
        table.insert(self.info, item)
    end,
    remove = function (self, item)
        table.remove(self.info, item)
    end,
    check = function (self, item)
        for i, v in ipairs(self.info) do
            if v == item then return true end
        end
    end,
    new = function (self, o)
        o = o or {}
        self.__index = self
        setmetatable(o, self)
        return o
    end,
}

local a1 = Account:new()
local a2 = Account:new()
local a3 = Account:new()


a1:deposit(50)
a1:add("aaa")
a2:deposit(100)
a2:add("bbb")
a2:add("bbb")

print(a1.balance)
for _, v in ipairs(a1.info) do print(v) end
print(a2.balance)
for _, v in ipairs(a2.info) do print(v) end

Здесь info используется всеми объектами:

50
aaa
bbb
100
aaa
bbb

Как сделать информацию уникальной для каждого нового объекта?

РЕДАКТИРОВАТЬ. Обходной путь - я помещаю все «поля» в метод new, в то время как оставил методы в прототипе, но я не вижу, что это очень элегантно:

    new = function (self, o)
        o = o or {}
        o.balance = 0
        o.info = {}
        self.__index = self
        setmetatable(o, self)
        return o
    end,

Спасибо

1 Ответ

0 голосов
/ 02 апреля 2020

Ответ может быть проще, чем вы думаете; Вы присваиваете info в таблице "class". Вместо этого просто присвойте новую таблицу info каждому экземпляру в конструкторе:

function Account:new(instance)
   instance = instance or {}
   instance.info = {}
   setmetatable(instance, self)
   return instance
end

Обратите внимание, что в моем примере я удалил строку self.__index = self, потому что вы не должны делать это в конструкторе. Вместо этого назначьте его один раз после создания таблицы как Account.__index=Account

...