Pull to refresh

Comments 21

Неделя Lua ООП прямо. А по общему числу постов на эту тему на Хабре хоть сборник собирай.
Woman = {};
--наследуемся
extended(Woman, Person)

Было бы еще прикольнее писать Woman = extend(Person)

Если кто-то путается где ставить точку, а где двоеточие, правило следующее: если обращаемся к свойству — ставим точку (obj.name), если к методу — ставим двоеточие (obj:getName()).

Чтобы действительно не путать, лучше запомнить смысл двоеточия — это просто синтаксический сахар, который неявно добавляет к функции первый аргумент self. Можно было бы использовать точку, но тогда пришлось бы явно добавлять аргумент самим, чтобы иметь доступ к объекту, для которого вызван метод (документация).
Примерно так:
function extend(parent)
    local child = {}
    setmetatable(child,{__index = parent})
    return child
end
Лучший, на мой взгляд вариант — наследование от базового класса Object с предопределенными функциями new и extend.
Не понимаю плясок с бубном вокруг инкапсуляции и приватных полей в скриптовых языках. Нафига это там нужно, непонятно.
Без этой ерунды, ООП в lua добавляется буквально одной функцией.
Кроме того, private на самом деле еще более public, чем public, т.к. доступен всем без исключения, что, собственно, функция setName и демонстрирует. Но все еще хуже. Попробуйте создать два класса с приватными полями. Будите сильно удивлены (это я автору).
какая клевая и класическая для Lua бага ))
Прошу прощения у всех за этот косяк. Дело в том, что я никогда и не пользовался инкапсуляцией, а этот костыль прикрутил прямо во время написания статьи, чтобы не убивать ни одного кита. Был не прав, сейчас думаю как исправить.
Похоже и мне теперь нужно написать про ООП в Lua. Мой метод не использует setmetatable() и экономит ресурсы.
Кстати у вас глобальные переменные.
Я когда-то делал парсер для текстовых игр на Lua, получилось что-то вроде этого:

sixdays:new "room" ()       { room = true }
sixdays:new "player" ()     : moveto( room )
sixdays:new "apple_red" ()  { name = "red apple" }      : moveto( room )
sixdays:new "apple_green" (){ name = "green apple" }    : moveto( room )
sixdays:new "table_red" ()  { name = "red table" }      : moveto( room )
sixdays:new "table_green" (){ name = "green table" }    : moveto( room )

new — создание нового объекта с глобальным именем, указанным в кавычках
в скобках можно указать, от кого наследуемся (список)
в фигурных скобках конструктор
Спасибо, что поделились опытом.
Я давно присматриваюсь к Lua.
V-REP скриптуется на Lua — роботы-Lua)
А лучше прочитать Иерусалимски — Programming in Lua. Удивительно хорошо написана и легко читается.
Спасибо, кстати первая редакция книги доступна online
Если кто не пробовал, рекомендую посмотреть на Squirrel
www.squirrel-lang.org
Очень похоже на Lua, но ООП без костылей.
белка хороша, но слишком редка. Я видел всего один игровой движок (а луа я использую именно в них), в котором был squirrel, да и тот умер.
К тому же, луа быстрее.
Lua быстрее, но имхо это далеко не везде критично во встроенном скриптовом интерпретаторе.
Кстати, для белки еще есть отличный биндинг SqPlus.
Статья изменилась, просьба перечитать. Пофиксил инкапсуляцию.
Пример: inherit.lua
-------------------------------------------------------------
local Object = {}

function Object:new(properties)
	properties = properties or {}
	setmetatable(properties, self)
	self.__index = self
	return properties
end

function Object:inherit(properties)
	return self:new():new(properties)
end
-------------------------------------------------------------
local Person = Object:inherit(
{
	name = "default"
})

function Person:get_name()
	return self.name
end
-------------------------------------------------------------
local Coconut = Person:inherit(
{
	cosplay = "maiden"
})

function Coconut:get_name()
	return "sexy " .. self.name
end

function Coconut:get_cosplay()
	return self.cosplay
end
-------------------------------------------------------------
person1 = Person:new()
print("person1: name=" ..	person1.name ..
	"\tget_name()=" ..	person1:get_name())
-------------------------------------------------------------
person2 = Person:new({name = "Human"})
print("person2: name=" ..	person2.name ..
	"\tget_name()=" ..	person2:get_name())
-------------------------------------------------------------
coconut1 = Coconut:new()
print("coconut1: name=" ..	coconut1.name ..
	"\tget_name()=" ..	coconut1:get_name() ..
	"\tcosplay=" ..		coconut1.cosplay ..
	"\tget_cosplay()=" ..	coconut1:get_cosplay())
-------------------------------------------------------------
coconut2 = Coconut:new({name = "Coconut", cosplay = "nurse"})
print("coconut2: name=" ..	coconut2.name ..
	"\tget_name()=" ..	coconut2:get_name() ..
	"\tcosplay=" ..		coconut2.cosplay ..
	"\tget_cosplay()=" ..	coconut2:get_cosplay())
-------------------------------------------------------------

Вывод:
person1: name=default get_name()=default
person2: name=Human get_name()=Human
coconut1: name=default get_name()=sexy default cosplay=maiden get_cosplay()=maiden
coconut2: name=Coconut get_name()=sexy Coconut cosplay=nurse get_cosplay()=nurse
Sign up to leave a comment.

Articles