Skip to content

Классы

Все объекты в INSTEAD, кроме переменных, атрибутов и обработчиков содержат методы (функции), которые вызываются при работе движка.

Когда в коде вашей игры, вы пишете что-то вроде:

lua
obj {
    nam = 'стол';
    dsc = "Тут стоит {стол}.";
}

То вы создаёте таблицу Lua, в которой кроме nam и dsc определены многие другие вещи. Например, метод disable(). Когда вы пишете:

lua
obj {
    nam = 'стол';
    dsc = "Тут стоит {стол}.";
}:disable()

Вы у созданного только что объекта 'стол' вызываете метод disable(). (Вызывается функция disable объекта и в качестве 1-го параметра передаётся этот же объект).

На самом деле, даже когда вы создаёте объект с помощью obj, вы неявно вызываете метод (функцию) new у класса obj: obj.new { описатель объекта }

Классы -- удобный способ описать иерархию объектов INSTEAD, а также реализовать свои типы объектов. Например, вот как определяется класс obj (с сокращениями):

lua
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 в текущей комнате, тогда:

lua
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, которая включается в вашу игру, определены такие переменные;

lua
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 определять в начале модуля:

lua
local std = stead

Это обезопасит ваш модуль от коллизий с игровыми глобальными переменными.