Объекты и контексты |
При работе в программе мы сталкиваемся с такими понятиями как организация, документ, товар, основное средство и т.д. Каждое из таких понятий характеризуется определенным набором данных и свойств. Например, у документа есть дата, номер и сумма. Такой набор данных, связанных одним понятием, мы будем называть объектом. В большинстве своем все наши операции и выражения будут обрабатывать либо данные объектов, либо сами объекты.
Приведем пример простейшей операции выдачи денег в подотчет:
Проводка(Д71, Лицо1, Сумма, К50_1);
Под переменной Сумма в данном случае мы подразумеваем сумму документа, для которого выполняется проводка. Иными словами можно сказать, что Сумма - это поле данных или переменная объекта Документ. Очевидно, что у каждого документа есть еще много других полей (переменных). В этот набор входят, по меньшей мере, все те данные, которые мы заполняли, создавая или редактируя документ.
Как обращаться к переменным объекта? Для этого используется следующая форма записи:
Документ.Сумма
Здесь Документ - это имя объекта, Сумма - имя переменной объекта, "." (точка) между ними - символ уточнения - указывает на обращение к переменной объекта. Наш пример с функцией Проводка можно записать в следующем виде:
Проводка(Д71, Документ.Лицо1, Документ.Сумма, К50_1);
И эта, и ранее приведенная запись являются правильными. Заметим, что в первом случае можно не уточнять, что Сумма относится к документу, и использовать, таким образом, короткую форму записи. Функция Проводка выполняется в операции, закрепленной за документом, и когда мы обращаемся к переменной Сумма, то достаточно очевидно, что мы обращаемся именно к сумме документа (к чему же еще). В данном случае, мы можем говорить о том, что объект Документ является контекстным или умалчиваемым (принимаемый по умолчанию), а обращение к любой переменной подразумевает обращение к переменной этого объекта.
В ходе выполнения операции возможны случаи, когда вместо документа будет установлен другой контекстный объект. Например, при переборе строк накладной текущим контекстом будет объект типа строка документа - мы называем его Наим (от слова наименование). Кроме того, есть специальная функция - Установить - позволяющая Вам самостоятельно установить объект, который будет считаться текущим контекстом.
Вернемся к нашему примеру. Указывая аналитический признак по дебету 71-го счета, мы написали - Лицо1. Что такое Лицо1? С точки зрения оформления документа - это сотрудник, которому выдаются деньги. С точки же зрения правила операции это объект, точнее даже объект аналитического учета. Помня о том, что в документе у нас могут быть два лица - Лицо1 и Лицо2 - можно сказать, что в объекте типа Документ имеются два других объекта Лицо1 и Лицо2, т.е. имеются два подобъекта.
Предположим теперь, что 71 счет разбит у нас на субсчета, в соответствии с отделами в нашей организации. Выдавая деньги в подотчет, мы должны будем сделать проводку не просто на 71 счет, а на субсчет того отдела, к которому относится данный сотрудник. Как решить эту задачу?
При занесении данных в справочник сотрудников будем указывать в поле данных ‘Субсчет’ тот субсчет 71-го счета, к которому относится данный сотрудник. Тем самым мы фактически определим переменную Субсчет в объекте Лицо1, и в дальнейшем сможем использовать ее при составлении правила операции.
Проводка(Лицо1.Субсчет, Лицо1, Сумма, К50);
Запись ‘Лицо1.Субсчет’ означает, что мы обращаемся к полю Субсчет объекта Лицо1. Уточнение в данном случае является обязательным, так как объект Лицо1 в отличие от объекта Документ не является контекстным. Написав просто переменную Субсчет, мы можем получить сообщение об ошибке, так как контекстный объект Документ в общем случае не содержит такой переменной.
Если записать предыдущий наш пример без использования контекстного объекта, то правило будет выглядеть следующим образом:
Проводка(Документ.Лицо1.Субсчет, Документ.Лицо1, Документ.Сумма, К50);
Остановимся более подробно на записи Документ. Лицо1.Субсчет. Что мы делаем в данном случае - берем объект Документ, у него берем подобъект Лицо1, а у этого подобъекта берем поле Субсчет. Если бы у объекта Лицо1 были бы подобъекты, то эту цепочку можно было бы продолжить. Здесь очень важно понять, что везде, где у нас определен объект типа документ, всегда можно обратиться к его переменным и подобъектам. И у этих подобъектов можно обратиться к их переменным и подобъектам и т.д.
Приведем еще один пример обращения к полям объекта. В правиле по закрытию 44 счета можно написать следующую операцию.
ДляВсех(Лиц("44"))
{ C = СКД44 / .ОК46;
Проводка(Д46_10, C * .ОК46_10, К44, Лицо);
Проводка(Д46_20, C * .ОК46_20, К44, Лицо);
}
В данном случае мы перебираем всех лиц, имеющих сальдо или обороты по 44-му счету. При переборе в операцию вносится контекстный объект Лицо. Псевдопеременная СКД44 (сальдо конечное дебетовое по 44-му счету) в случае, когда объект типа Лицо является контекстным, трактуется как сальдо по 44-му счету в разрезе данного лица. Аналогичная ситуация и по 46-му счету. Как же в таком случае получить общее сальдо или в данном случае обороты по 46 счету? Для этого используется запись вида ‘.ОК46’. Точка в начале записи говорит о том, что мы обращаемся к базовому значению переменной, вне текущего контекста. Запись с точкой перед именем переменной может использоваться и в других случаях. Не вдаваясь в сложные теоретические обоснования, попробуем пояснить это на примерах:
Вариант
1
Вариант 2
ДляВсех(Наименований)
ДляВсех(Наименований)
{ А += СуммаСебест;
} { .А +=
СуммаСебест;}
Сообщить(А);
Сообщить(А);
В варианте 1 при выполнении функции ‘Сообщить’ будет выдано сообщение об ошибке, в связи с отсутствием переменной ‘А’, в вариатне 2 все пройдет нормально. В чем разница? В точке перед именем переменной ‘А’ при суммировании в цикле. В первом случае переменная создается внутри цикла и при его завершении будет уничтожена, и следовательно в момент выполнения функции ‘Сообщить’ ее уже не будет. Во втором случае переменная ‘А’ создается в базовом контексте, т.е. как бы вне цикла, и соответственно не уничтожается при его завершении.
Набор объектов, с которыми Вам придется оперировать в программе, строго фиксирован и достаточно невелик. Наиболее типичными среди них являются объекты типа Лицо, Документ и Наим. В дальнейшем мы приведем более подробное описание всех объектов, используемых в системе.
Как сравниваются два объекта в СБиС++, например, в выражении оОбъект1 == оОбъект2.
Если оба объекта нулевые (равны "Нет",
пустые),
то они равны.
Иначе Если один из них нулевой, а другой - нет,
то они не равны
Иначе (оба не нулевые)
Если оба объекта не имеют записей, то они равны
Иначе Если один объект имеет запись, а другой - нет,
то они не равны
Иначе (оба объекта имеют записи)
Если записи имеют ОДНОГО И ТОГО ЖЕ хозяина
и ОДИНАКОВЫЙ адрес, то они равны
Иначе
они не равны
Поясним на примере действие этого алгоритма. В выражении:
перем оОбъект =
Выборка("Организации");
оОбъект.Загрузить(0x12345);
оОбъект.МоёДополнительноеПоле = "1234";
записью будет запись выборки (а МоёДополнительноеПоле в эту запись НЕ войдёт ). Хозяином записи будет выборка "Организации". При сравнении важно, чтобы записи принадлежали не просто к одинаковой выборке, а к ОДНОМУ экземпляру выборки. Например:
перем оТаблица1 =
Выборка("Организации");
перем оОбъект1 = оТаблица1.Запись();
оОбъект1.Загрузить( 0x26B );
перем оОбъект2 = оТаблица1.Запись();
оОбъект2.Загрузить( 0x26B );
перем оТаблица2 = Выборка("Организации");
перем оОбъект3 = оТаблица2.Запись();
оОбъект3.Загрузить( 0x26B );
Сообщить("Равны ли оОбъект1 и оОбъект2? " + (оОбъект1 == оОбъект2)
);
Сообщить("Равны ли оОбъект1 и оОбъект3? " + (оОбъект1 == оОбъект3)
);
В результате получим:
• Равны ли оОбъект1 и оОбъект2? – Да;
• Равны ли оОбъект1 и оОбъект3? - Нет.
Важно отметить, что в СБиС++ два экземпляра одной таблицы всегда равны, т.е. замена в этом примере функции Выборка на Таблица вызвала бы ответ "Да" и во втором случае.