Экземпляр класса Lua с вложенными таблицами - PullRequest
1 голос
/ 30 мая 2010

Простая игра Lua с простым классом, например:

creature = class({ 
name = "MONSTER BADDY!",

stats = { power = 10, agility = 10, endurance = 10, filters = {} },

other_things = ...
})

creatureA = creature.new()

creatureB = creature.new()

creatureA.name = "Frank"

creatureB.name = "Zappa"

creatureA.stats.agility = 20

creatureB.stats.power = 12

- бла-бла-бла

Не табличные значения индивидуальны для каждого экземпляра, но табличные значения общий для всех экземпляров, и если я изменю значение stats.X в одном экземпляре, все остальные экземпляры видят ту же таблицу статистики.

Q1: моя OO-реализация несовершенна? Я попытался LOOP и тот же результат, в моей логике есть фундаментальный недостаток?

Q2: Как бы у каждого экземпляра существа была своя собственная таблица статистики (и вспомогательные таблицы)?

PS. Я не могу сгладить свою таблицу классов, так как она немного сложнее, чем пример, а другие части кода упрощены с помощью этой реализации вложенной таблицы.

Ответы [ 4 ]

3 голосов
/ 30 мая 2010

Это работает так, потому что экземпляры классов имеют таблицу классов, установленную как __index в своей метатаблице (ну, большинство реализаций работают именно так) Таким образом, если вы получаете доступ к creatureA.stats (и он не может найти stats на creatureA, следовательно, падает до __index), он возвращает creature.stats. Возможно, вам стоит прочитать Справочное руководство по Lua 5.1: Metatables

Вы не сможете объявить переменные для каждого экземпляра в конструкторе таблицы класса (если вы не скопируете все из таблицы классов в экземпляр, что будет довольно дорого)

Вам придется делать это в любой функции инициализатора, которую использует реализация вашего класса:

creature = class
{
     __init = function(self, ...)
         self.stats = {power = 10, agility = 10, endurance = 10, filters = {}}
     end,
}
3 голосов
/ 31 мая 2010

class не является стандартной функцией в Lua. Вы не говорите, позаимствовали ли вы его у Роберто, прокатили или что-то еще. Но я предполагаю, что вы хотите изменить метод new, чтобы он делал глубокую копию прототипа вместо мелкой копии:

function deep_copy(v)
  if type(v) == 'table' then
    local u = { }
    for k, v in pairs(v) do
      u[k] = v
    end
    setmetatable(u, getmetatable(v))
    return u
  else
    return v
  end
end

(Внимание: я не пытался скомпилировать этот код, не говоря уже о его запуске.)

0 голосов
/ 31 мая 2010

Эта ваша функция с именем class выглядит подозрительно. Я бы пошел для простейшего кода. Вот файл класса монстров. Ничего особенного, и некоторые люди скажут, что ему не хватает пуха, но, по крайней мере, я тоже смогу прочитать код на следующей неделе.

-- Class object

monster = {}
monster.__index = monster

-- Class methods

function monster.new(name)
    local o = {}
    o.name = name
    o.stats = {power = 10, agility = 10, endurance = 10, filters = {}}
    setmetatable(o, monster)
    return o
end

function monster:shout()
    print('Aaaaaaa! My name is ' .. self.name .. '!')
end

А вот и вывод:

> lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require 'monster'
> m = monster.new('Katla')
> m:shout()
Aaaaaaa! My name is Katla!
0 голосов
/ 30 мая 2010

При создании новой creature вы всегда можете создать для нее новую таблицу stats, если вы не хотите, чтобы она была опубликована.

creature = class({ 
    name = "MONSTER BADDY!",
    stats = stats.new({ power = 10, agility = 10, endurance = 10, filters = {} }),
    other_things = ...
})

Мощность, ловкость и т. Д. Будут передаваться в качестве аргументов в конструкторе для stats.

...