Эмуляция ООП в 1С8

Скорее экспериментально-теоретическое, чем практическое руководство по использованию ООП В 1С8.

К великому нашему прискорбию в 1С 8.0 не включено объектно-ориентированное программирование. Не будем обсуждать в данной статье почему разработчики решили обойтись без него.

В семерке тоже не было ООП. Некоторые умельцы реализовывали ООП с помощью внешних обработок. Мы пойдем другим путем – документированным.

Как говорится, если нельзя, но очень хочется, то можно.

Вы увидите, что основная парадигма ООП реализуется штатными средствами 1С 8.0.

Что такое объект в понятиях ООП?

Объект состоит из свойств и методов.

Объект может наследовать методы и свойства от другого объекта – предка.

Реализация в 1С 8.0

Для моделирования свойств объектов прекрасно подойдет объект типа «Структура», где можно хранить любые свойства любого типа.

Для реализации методов объектов будем использовать общие модули, по одному на каждый объект. В этих модулях будем описывать методы объекта в виде функций с именами ТипОбъекта_ИмяМетода. Хотелось бы конечно писать просто ОбмяМетода(Параметры), но придется писать примерно вот так: Метод(Об, ИмяМетода, Параметры).

Для передачи параметров опять же будем использовать только один параметр типа структура, который может содержать в себе любое количество параметров. К сожалению 1С не поддерживает вызов процедур с произвольным количеством и порядком вызова параметров.

Каждый объект содержит по ключу «Тип» название своего типа, для вызова соответствующего метода используется документированная функция «Выполнить».

Если метод не найден у объекта, он ищется у предка. Тип предка определяется через вызов у объекта метода Предок, если метод определен.

Если вызываемый метод не определен, система ничего не делает.

В методе можно вызвать метод предка, примерно так Предок(Об, ИмяМетода, Параметры).

Свойства можно назначать непосредственно, но для обеспечения контроля над свойствами лучше использовать функции Установить(Об, Свойство, Зн) и Получить(Об, Свойство).

Можно написать перехватчики событий установки-чтения свойств. Они носят имя ТипОбъектастановить и ТипОбъекта_Получить. Если ТипОбъектастановить возвращает истину, то свойство устанавливается, если ложь, то нет (этот обработчик может уже установить значения свойства и повторно его ставить не надо или запретить изменение свойства).

Конструктор объекта описывается в функции ТипОбъектаоздать.

Деструктор объекта описывается в функции ТипОбъектадалить. К сожалению, все вызовы деструкторов нужно вызывать явно, т.к. в 1С 8.0 нельзя отследить момент удаления локальной переменной.

Таким образом для реализации ООП достаточно 6 функций:

·         Создать

·         Метод

·         Предок

·         Установить

·         Получить

·         Удалить

Невероятно, но факт.

В принципе, объекты 1С 8.0 (документы, справочники и т.п.) можно рассматривать уже как готовые объекты. Действительно, у них можно получить тип. Кроме того, они обладают набором свойств. Таким образом, можно унифицировать работу с объектами через вышеуказанные шесть методов.

И если завтра вместо документа вы решите использовать справочник возможно в коде, ничего не придется менять.

Резюме.

Как я показал, ООП в 1С 8.0 можно реализовать легко и красиво, добавив только  6 функций.

Зачем это нужно?

Некоторые библиотеки функций удобнее реализовать в виде библиотеки классов.

Например, списание по партиям удобно реализовать в виде объекта ОчередьПартий, а каждое из списаний по товарам, по долгам будет наследовать от базовой очереди, внося новые свойства.

Также можно реализовать библиотеки для работы с файлами, строками и т.п.

Единственно, нужно учитывать, что объектно-ориентированный подход в нашем случае нужно применять там, где прозрачность и понятность разработки важнее быстродействия, т.к. методы интерпретатора Выполнить все же медленнее скомпилированного кода 1С.

И все же, если в очередном релизе появится метод ВыполнитьФункцию(Имя Функции, Параметры), все ограничения по скорости будут сняты и ООП восторжествует. Видите, как для этого мало надо!

Кроме того, если использовать функцию Шаблон и вместо Структуры Список значений, то подобное ООП можно реализовать и в 7.7, правда вся реализация методов должна быть в одном глобальном модуле (в семерке нельзя реализовать несколько модулей).

Ну конечно бы хотелось, чтобы для всех 6 методов были введены операторы, но это уже от лукавого. Аминь!

Результат работы:

Приложение.

Здесь я порекомендую разработчикам 1С 8.0 операторы для функций.

 

Создать = СоздатьОбъект ТипОбъекта

Метод = Обетод(Параметры)

Предок = Об::Метод(Параметры)

Установить = Обвойство=Зн;

Получить = Обвойство=Получить;

Удалить = УдалитьОбъект Об.

//Реализация объекта 1

Функция Объект1_Создать(Прм="")

КонецФункции

Функция Объект1_Печать(Я, Прм="")

                Сообщить("Я объект 1");

                Возврат 1;

КонецФункции

 

Функция Объект1_Известить(Я, Прм="")

                Сообщить(Получить(Я, "Информация"));

                Возврат 1;

КонецФункции

 

 

//Реализация объекта 2

Функция Объект2_Создать(Прм="")

КонецФункции

 

Функция Объект2_Предок(Я, Прм="")

                Возврат "Объект1";

КонецФункции

 

Функция Объект2_Известить(Я, Прм="")

                Сообщить("1С 8.0 - объектно-ориентированная среда!!! "+Прм);

КонецФункции

 

 

//Реализация объекта 3

Функция Объект3_Создать(Прм="")

КонецФункции

 

Функция Объект3_Предок(Я, Прм="")

                Возврат "Объект2";

КонецФункции

 

Функция Объект3_Печать(Я, Прм="")

                Сообщить("Я объект 3");

                Предок(Я, "Известить", "Верите?");

                Возврат 3;

КонецФункции

 

 

//// ФУНКЦИИ, РЕАЛИЗУЮЩИЕ ООП В 1С 8.0 /////

 

//Вызывает функцию, определенную в предке

Функция Предок(Об, Метод, Прм="", Сработал=ложь)

                Перем Результат, Тип, Предок;

               

                //Получаем тип объекта

                Тип=Обип;

 

                Сработал=истина;

                Попытка

                               Предок=Вычислить(Тип+"_Предок(Об, Прм)");                         

                               Попытка

                                               Результат=Вычислить(Предок+"_"+Метод+"(Об, Прм)");                   

                                               Возврат Результат;

                               Исключение

                               КонецПопытки;

                Исключение

                КонецПопытки;

                Сработал=ложь;

                Возврат Неопределено;

КонецФункции

 

Функция Метод(Об, Метод, Прм="", Сработал=ложь)

                Перем Тип;

               

                Сработал=истина;

               

                //Получаем тип объекта

                Тип=Обип;

               

                //Сначала пробуем просто вызвать метод самого объекта

                Попытка

                               Возврат Вычислить(Тип+"_"+Метод+"(Об, Прм)");                  

                Исключение

                КонецПопытки;

               

                Сработал=ложь;

                //Затем пробуем вызвать метод у предка объекта

                Возврат Предок(Об, Метод, Прм);

КонецФункции

 

 

//Создает объект

Функция Создать(Тип, Прм="")

                Об=Новый Структура;

                Обставить("Тип",Тип);

                Метод(Об, "Создать", Прм);

                Возврат Об;

КонецФункции

 

Функция Установить(Об, Свойство, Зн)

                Перем Сработал, Рез;

                Прм=Новый Структура;

                Прмставить("Свойство", Свойство);

                Прмставить("Значение", Зн);

                Рез=Метод(Об, "Установить", Прм, Сработал);

                Если (Не Сработал) ИЛИ (Рез=Истина) Тогда

                               Обставить(Свойство, Зн);

                КонецЕсли;

                Возврат Зн;

КонецФункции

 

Функция Получить(Об, Свойство)

                Перем Сработал, Зн;

                Прм=Новый Структура;

                Прмставить("Свойство", Свойство);

                Зн=Метод(Об, "Получить", Прм, Сработал);

                Если Не Сработал Тогда

                               Если Не Обвойство(Свойство, Зн) Тогда

                                               Зн=Неопределено;

                               КонецЕсли;

                КонецЕсли;

                Возврат Зн;

КонецФункции

 

 

Процедура Сформировать(Элемент)

                // Вставить содержимое обработчика.

                Об1=Создать("Объект1");

                Об2=Создать("Объект2");

                Об3=Создать("Объект3");

                Рез1=Метод(Об1, "Печать");

                Рез2=Метод(Об2, "Печать");

                Рез3=Метод(Об3, "Печать");

                Сообщить("Результаты: "+Рез1+" "+Рез2+" "+Рез3);

                Сообщить("Сначала информации нет:"+Получить(Об1, "Информация"));

                Установить(Об1, "Информация", "Я храню некую информацию");

                Сообщить("Потом мы ее устанавливаем:"+Получить(Об1, "Информация"));

КонецПроцедуры

 

Текст обработки можно скачать