Луа - проблемы с пониманием ООП - PullRequest
0 голосов
/ 06 октября 2018

У меня немало проблем с пониманием ООП в Lua.Согласно программированию в Lua, я могу создавать классы очень просто, например:

Class = {}

function Class:new()
  setmetatable({}, self)
  self.__index = self

  self.a = 1

  return self
end

function Class:incr()
  self.a = 2 * self.a
  return self
end

Однако, когда я иду и создаю экземпляр, он не работает так, как я ожидал:

-- works as expected
instance = Class:new()
instance:incr()
print(instance) --> table 0x(address)
print(instance.a) --> 2

-- it gets weird from here on
other = Class:new()
other:incr():incr()
print(other) --> table 0x(same address)
print(other.a) --> 4

print(instance.a) --> 4

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 06 октября 2018
function Class:new()
...
   return self -- self is -> Class = {}
end

other    = Class:new() -- Other will get Class = {} when you call new()
instance = Class:new() -- same here
print(other)    -- will print Class = {}
print(instance) -- will print Class = {}
0 голосов
/ 06 октября 2018

Пример в PiL откровенно запутанный.Он описывает то, что называется наследование прототипа .Это означает, что нет никакого различия между классами и объектами.Вот версия вашего new метода, которая немного более правильна:

function Class:new()
  -- Note that self refers to the class, here. We have to return a new object.
  self.__index = self
  local o = {a=1}
  setmetatable(o, self)
  return o
end

Но у нас все еще есть проблема: поскольку наш конструктор устанавливает переменную экземпляра, мы не можем использовать ее для создания подклассов.Если мы попробуем, у всех этих подклассов будет a, установленный внутри себя, а не в их экземплярах.Мы могли бы определить init метод, который мы должны вызывать каждый раз, когда создаем новый экземпляр, но это было бы больно.Вот один из возможных способов разделения классов и объектов:

-- Make sure every class has an __index pointing to itself. This lets it be the
-- metatable for both instances and subclasses.
local Class = {}
Class.__index = Class

function Class:new()
  local o = {a=1}
  setmetatable(o, self)
  return o
end

function Class:incr()
  self.a = 2 * self.a
  return self
end

-- To inherit, simply use Class as the metatable.
local Subclass = {}
Subclass.__index = Subclass
setmetatable(Subclass, Class)

Таким образом, new используется только для создания экземпляров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...