Мне нравится думать, что ООП - это инкапсуляция данных внутри контейнера (объекта) в сочетании с подмножеством операций, которые могут быть выполнены с этими данными. Это намного больше, но давайте предположим, что это простое определение - это все и создадим что-то на Lua из него (также некоторое знакомство с другими реализациями ОО может быть хорошим стимулом для читателя).
Как может знать любой, кто мало знаком с Lua, таблицы - отличный способ хранить пары ключ-значение, и в сочетании со строками все становится очень интересным:
local obj = {} -- a new table
obj["name"] = "John"
obj["age"] = 20
-- but there's a shortcut!
print("A person: " .. obj.name .. " of the age " .. obj.age)
Доступ к строковым значениям в качестве ключей в таблице можно получить очень похожим образом на элементы структуры в C или открытые члены объекта в C ++ / Java и аналогичных языках.
А теперь крутой фокус: давайте объединим это с анонимными функциями.
-- assume the obj from last example
obj.hello = function ()
print("Hello!")
end
obj.goodbye = function ()
print("I must be going.")
end
obj.hello()
obj.goodbye()
Отлично, верно? Теперь у нас есть средства для хранения функций внутри наших таблиц, и снова вы можете видеть, что это похоже на то, как методы используются в других языках ООП. Но чего-то не хватает. Как мы можем получить доступ к данным, которые принадлежат нашему объекту в наших определениях методов? Это обычно решается путем изменения сигнатуры функций в таблице на что-то вроде этого:
-- assume the obj from last example
obj.inspect = function (self)
print("A person: " .. self.name .. " of the age " .. self.age)
end
obj.hello = function (self)
print(self.name .. ": Hello! I'm " .. self.name)
end
obj.goodbye = function (self)
print(self.name .. ": I must be going.")
end
-- now it receives the calling object as the first parameter
obj.inspect(obj) -- A person: John of age 20
obj.hello(obj) -- John: Hello! I'm John
obj.goodbye(obj) -- John: I must be going
Это решает это простым способом. Возможно, проведя параллель с тем, как все работает в Python (методы всегда получают явное «я»), вы можете узнать, как это работает в Lua. Но, парень, разве не неудобно явно передавать все эти объекты в вызовах наших методов? Да, это меня тоже беспокоит, так что есть еще один способ помочь вам в использовании ООП:
obj:hello() -- is the same as obj.hello(obj)
Наконец, я только что поцарапал поверхность того, как это можно сделать. Как было отмечено в комментарии Кевина Вермеера , Lua Users Wiki является отличным источником информации по этой теме, и там вы можете узнать все о том, как реализовать другие важные аспекты ООП, которые в этом ответе не учитывались (частные члены, как создавать объекты, наследование, ...). Имейте в виду, что этот способ ведения дел является небольшой частью философии Lua, предоставляя вам простые ортогональные инструменты, способные создавать более сложные конструкции.