Луа ой глубоко копировать таблицу - PullRequest
0 голосов
/ 09 декабря 2018

Мой код глубокой копии:

function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
    copy = {}
    for orig_key, orig_value in next, orig, nil do
        copy[deepcopy(orig_key)] = deepcopy(orig_value)
    end
    setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
    copy = orig
end
return copy
end

Я пытаюсь реализовать это, чтобы использовать oop, используя self, но не могу заставить его работать, вот что я пытался до сих пор

function block:deepcopy()
local orig_type = type(self)
local copy
if orig_type == 'table' then
    copy = {}
   for orig_key, orig_value in next, self, nil do
       copy[self:deepcopy(orig_key)] = deepcopy(orig_value)
   end
   setmetatable(copy, self:deeepcopy(getmetatable(self)))
else
    copy = orig
end
return copy

1 Ответ

0 голосов
/ 09 декабря 2018

В версии функции ООП self:deepcopy(something) с синтаксисом метода (двоеточие) не выполняет то, что вам нужно.Это эквивалентно self.deepcopy(self, something);второй аргумент something игнорируется, и вы просто пытаетесь повторно копировать один и тот же self снова и снова, пока не возникнет переполнение стека.Вы должны сделать self.deepcopy(something) с точкой, чтобы передать something в качестве аргумента self (копируемый аргумент).

Вызов self.deepcopy внутри определения метода deepcopy предполагает, чтоу каждой подтаблицы есть функция self.deepcopy.Если нет, вы получите ошибку «попытка вызвать нулевое значение».Но вы можете сделать это, если хотите, чтобы у каждой подтаблицы была своя собственная версия deepcopy, которая используется при копировании непосредственных потомков этой таблицы (ключей, значений, метатабельных).Например, у вас может быть подтаблица, чей метод deepcopy не копирует метатаблицу.Вот базовая версия, в которой для подтаблицы используется тот же метод deepcopy:

local block = {}

function block:deepcopy()
    if type(self) == 'table' then
        local copy = {}
        for key, value in pairs(self) do
            copy[self.deepcopy(key)] = self.deepcopy(value)
        end
        return setmetatable(copy, self.deepcopy(getmetatable(self)))
    else
        return self
    end
end

block.a = { a = 10, deepcopy = block.deepcopy }
block:deepcopy() -- works

block.a = { a = 10 }
block:deepcopy() -- error: "attempt to call a nil value (field 'deepcopy')"

Но вам не нужно вообще переписывать функцию, чтобы использовать ее в объектно-ориентированном стиле.Попробуйте использовать ваше первое определение deepcopy.Выполните object.deepcopy = deepcopy, а затем позвоните object:deepcopy(), и вы получите копию объекта.

...