Какой наиболее эффективный способ реализации классов в Lua?

#lua

#lua

Вопрос:

Под эффективным я подразумеваю производительность. Если вам нужно быстро получить доступ к членам класса, например, при рисовании пользовательского интерфейса, каков наилучший способ их индексирования?

Насколько я понимаю, табличные классы используют меньше памяти и быстрее создают экземпляры, в то время как классы на основе замыкания имеют более быстрые вызовы функций и позволяют вам иметь закрытые поля, которые быстро индексируются, поскольку они хранятся как значения upvalues . Какая наилучшая реализация для ситуации, подобной приведенному ниже примеру класса?

 -- Example of Table-based Class

local class = {}
class.x = 0
class.y = 0
class.w = 0
class.h = 0

-- Draw would be called for potentially dozens of instances many times per second
function class:Draw()
    draw_rect(self.x, self.y, self.w, self.h)
end
  
 -- Example of Closure-based class

local function class(_x, _y, _w, _h)
  -- the new instance
  local self = {
    -- public fields
    visible = false
  }

  -- private fields are locals
  local x, y, w, h = _x, _y, _w, _h

  function self.SetPos(_x, _y)
    x = _x
    y = _y
  end

  function self.GetPos()
    return x, y
  end

  function self.GetVisible()
    return self.visible
  end

  -- return the instance
  return self
end

local obj = class(10, 20, 40, 80)
print(obj.GetPos()) --> 10, 20

obj.SetPos(50, 100)
print(obj.GetPos()) --> 50, 100

obj.x = 21
obj.y = 42
print(obj.GetPos())  --> 50, 100 (unchanged, private)

obj.visible = true
print(obj.GetVisible()) -- true (public)
  

Комментарии:

1. Чтение upvalue происходит значительно быстрее, чем индексация таблицы. Но как реализовать ООП только с повышающими значениями без таблиц?

2. Не может быть, чтобы накладные расходы на вызов функции для рендеринга пользовательского интерфейса были вашим узким местом. Что бы ни происходило внутри draw_rect , это займет значительно больше времени, чем время, необходимое для вызова class:Draw , независимо от того, какой метод вы используете.

3. @EgorSkriptunoff Я добавил пример того, как будет работать класс на основе замыкания. Похоже, это была бы лучшая реализация?

4. @NicolBolas Как вы думаете, не стоит беспокоиться о том, какую реализацию класса я должен использовать тогда?

5. @ghetto: Нет. Вы должны беспокоиться о производительности, если это становится проблемой, и даже тогда вы должны использовать профилировщик, чтобы сообщить вам, где на самом деле проблема с производительностью, а не предполагать, где она будет. Единственный раз, когда вы должны упреждающе решать проблему производительности, — это если у вас есть знания конкретной предметной области, достаточные для того, чтобы заранее сообщить вам, что производительность будет проблемой в определенном месте.