Классы
Все объекты в INSTEAD, кроме переменных, атрибутов и обработчиков содержат методы (функции), которые вызываются при работе движка.
Когда в коде вашей игры, вы пишете что-то вроде:
obj {
nam = 'стол';
dsc = "Тут стоит {стол}.";
}То вы создаёте таблицу Lua, в которой кроме nam и dsc определены многие другие вещи. Например, метод disable(). Когда вы пишете:
obj {
nam = 'стол';
dsc = "Тут стоит {стол}.";
}:disable()Вы у созданного только что объекта 'стол' вызываете метод disable(). (Вызывается функция disable объекта и в качестве 1-го параметра передаётся этот же объект).
На самом деле, даже когда вы создаёте объект с помощью obj, вы неявно вызываете метод (функцию) new у класса obj: obj.new { описатель объекта }
Классы -- удобный способ описать иерархию объектов INSTEAD, а также реализовать свои типы объектов. Например, вот как определяется класс obj (с сокращениями):
std.obj = std.class { -- определяем класс
__obj_type = true; -- тип объектов (функция is_obj)
with = function(self, ...)
-- ... реализация конструкции :with
end;
new = function(self, v)
-- реализация конструктора obj { }
end;
-- другие методы
-- ...
display = function(self) -- отображение объекта
local d = std.call(self, 'dsc')
return d
end;
-- другие методы
-- ...
};Обратите внимание на метод display, этот метод служит для отображения объекта в сцене. Как видите, он просто вызывает 'dsc' у объекта, с помощью std.call (вызов функции или строки).
Теперь представим себе, что вы хотите сделать класс объектов, у которых в темноте пропадает описатель. Признаком темноты является переменная darkroom в текущей комнате, тогда:
darkobj = std.class ({ -- определяем класс
__darkobj_type = true; -- тип объектов (функция is_obj)
display = function(self) -- отображение объекта
if not here().darkroom then
local d = std.call(self, 'dsc')
return d
end
end;
}, std.obj);
darkobj {
nam = 'кот';
dsc = '{Кот} виден при свете.'
}Обратите внимание на скобки () и std.obj в последней строке. Таким образом мы дали понять, что наследуемся от класса std.obj. Все методы объекта, созданного при помощи darkobj, будут такими же, как и у obj, кроме метода display().
Если говорить об иерархии объектов STEAD3, то:
- room пронаследован от obj;
- dlg пронаследован от room;
- std.phr (фразы) пронаследован от obj;
std.dlg, std.room, std.phr и std.obj это внутренние имена классов. В стандартной библиотеке stdlib, которая включается в вашу игру, определены такие переменные;
local std = stead
local type = std.type
std.rawset(_G, 'std', stead) -- определим std для всех
include = std.include
loadmod = std.loadmod
rnd = std.rnd
rnd_seed = std.rnd_seed
p = std.p
pr = std.pr
pn = std.pn
pf = std.pf
obj = std.obj
stat = std.stat
room = std.room
menu = std.menu
dlg = std.dlg
me = std.me
here = std.here
from = std.from
new = std.new
delete = std.delete
gamefile = std.gamefile
player = std.player
dprint = std.dprintЭто сделано для удобства автора (легче написать include, вместо std.include или stead.include). Если же вы разрабатываете свой модуль, то рекомендуется пользоваться внутренними именами с префиксом std. Причём std определять в начале модуля:
local std = steadЭто обезопасит ваш модуль от коллизий с игровыми глобальными переменными.