Подобие Объектно-ориентированного программирования в 1С (ПООПс)
Разработка - Математика и алгоритмы
Возникла задача в которой было необходимо работать с объектами (не объекты метаданных) у которых есть множество одинаковых свойств и методов, но есть и свои специфические как свойства так и методы. Самым простым способом решения является ООП, но в 1С нет возможности работать с классами, инкапсуляцией, наследованием, полиморфизмом и так далее. Прочитал немногочисленные заметки и зарисовки, которые есть на этом сайте о том как предлагают реализовать подобные решения, но везде были свои "НО". Многие пишут, что не видят в ООП для 1С необходимости - это их дело, хотя и неосознанно они работают в "lite" версии ООП. Недостатки есть и в этой методике, которую хотелось предложить на Ваше обсуждение.
Для начала нам необходимо объединить данные и методы, этот процесс называется инкапсуляцией. Давайте посмотрим на текст следующего общего модуля:
Общий модуль "Класс_ФизическоеЛицо"
Функция Конструктор() Экспорт
МойОбъект = Новый Структура("Фамилия, Имя, _Пол", "", "", "");
МойОбъект.Вставить("ф", ЭтотОбъект);
Возврат МойОбъект;
КонецФункции
Функция Обращение(МойОбъект) Экспорт
Возврат МойОбъект.Фамилия+", "+МойОбъект.Имя;
КонецФункции
Функция Пол(МойОбъект, Пол="") Экспорт
Если НЕ ПустаяСтрока(Пол) Тогда
МойОбъект._Пол = Пол;
КонецЕсли;
Возврат МойОбъект._Пол;
КонецФункции
Здесь видно, что в качестве рабочей лошадки используется "Структура", хотя на ее место вполне подходит и "Соответствие". Первый недостаток заключается в том, что для вызова метода объекта необходимо использовать какое либо имя свойства для определения ссылки на модуль. Я для себя определил этим ключевым словом букву "ф". Но, методы и свойства чудесным образом объединились и теперь находятся в одной структуре (объекте) ссылку на который можно передавать и использовать почти в любом месте. Второй недостаток заключается в том, что контекст структуры не передается при вызове метода из этой структуры. Следовательно, необходимо первым параметром передать саму структуру. По этому все методы которые работают с данными объекта первым параметром получают саму структуру. Этот параметр я назвал «МойОбъект» (ну просто по тому что ключевое слово «ЭтотОбъект» занято). Третий недостаток заключается в том, что нет возможности сделать скрытыми свойства. Для себя я определил, что скрытыми будут те свойства, которые начинаются с символа «_» (подчеркивание) или их можно перенести в отдельное свойство (например, с именем «Скрытые»), состоящее из структуры только скрытых свойств. Что касается методов, то тут ситуация не такая однозначная. Ведь если процедуре или функции модуля не установить ключевое слово «Экспорт» то она будет недоступна из внешнего модуля, но она не будет доступна и для наследника. По этому если Вам необходимо использовать скрытый метод у наследников начинайте его так же как и скрытые свойства со знака «_» подчеркивания.
И так с инкапсуляцией мы разобрались. Теперь нам нужно решить вопрос с самым главным – наследованием. Смотрим следующий текст модуля:
Общий модуль "Класс_Сотрудник"
Функция КлассРодитель()
Возврат Класс_ФизическоеЛицо.ЭтотОбъект;
КонецФункции
Функция Конструктор() Экспорт
МойОбъект = КлассРодитель().Конструктор(); // Родительский конструктор
МойОбъект.Вставить("Должность", ""); // Добавляем новое свойство
МойОбъект.Вставить("ф", ЭтотОбъект); // Заменяем модуль набора методов
Возврат МойОбъект;
КонецФункции
Функция ОбращениеПоШтатке(МойОбъект) Экспорт // Новый метод этого класса
Возврат МойОбъект.Должность+" - "+МойОбъект.Ф.Обращение(МойОбъект);
КонецФункции
Функция Пол(МойОбъект, Пол=Неопределено) Экспорт // Модифицированный метод
Если (Пол<>Неопределено) и (НЕ (Пол="М" или Пол="Ж")) Тогда
Сообщить("Недопустимое значение при установке пола сотрудника!");
Возврат Неопределено;
КонецЕсли;
Возврат КлассРодитель().Пол(МойОбъект, Пол); // Вызываем родительский метод
КонецФункции
Функция Обращение(МойОбъект) Экспорт // Наследованный метод
Возврат КлассРодитель().СтрокаФИО(МойОбъект);
КонецФункции
Обратите внимание - каждый класс располагается в отдельном общем модуле. Теперь давайте смотреть, что у нас получилось. Конструктор вызывает родительский конструктор и получает от него все свойства, которые были определены в родительском классе, а если он вызывает своего родителя мы получим и свойства прародителя.. Четвертым недостатком является то, что если вы полностью переопределяете конструктор дочернего класса, то вы должны самостоятельно позаботиться о создании всех свойств, которые создаются родительским конструктором. Пятым недостатком и на мой взгляд самым существенным является то, что ВСЕ методы которые использует потомок необходимо объявлять в модуле потомка (в примере это функция «Обращение»). Небольшой ложкой меда здесь служит то, что при последующем или повторном наследовании эти методы можно перенести потомку простым копированием. Этот же недостаток заставляет отслеживать самостоятельно создание новых методов и копирование кода наследования в дочерние классы.
-
Но в результате мы получили объектный полиморфизм.
Давайте посмотрим, как будут работать наши классы в прикладном решении:
-
Использование в прикладном решении:
Сотрудник = Класс_Сотрудник.Конструктор();
Сотрудник.Фамилия = "Иванов";
Сотрудник.Имя = "Иван";
Сотрудник.Должность = "Программист 1С";
Клиент = Класс_ФизическоеЛицо.Конструктор();
Клиент.Фамилия = "Петров";
Клиент.Имя = "Петр";
Сообщить(Сотрудник.ф.Обращение(Сотрудник)); // Иванов, Иван
Сообщить(Клиент.ф.Обращение(Клиент)); // Петров, Петр
Сообщить(Сотрудник.ф.ОбращениеПоШтатке(Сотрудник)); // Программист 1С - Иванов, Иван
Сотрудник.ф.Пол(Сотрудник, "Н"); // Недопустимое значение при установке пола сотрудника!
Сотрудник.ф.Пол(Сотрудник, "М");
Сообщить(Сотрудник.ф.Пол(Сотрудник)); // М
Как видно из примера финальный код почти похож на стандартный ОПП (за исключением буквы «ф» перед методом и передачей самого объекта в качестве первого параметра) и такой подход можно смело назвать Подобием Объектно Ориентированного Программирования в 1С (ПООПс)
Если для Вашей задачи описанные недостатки будут малозначимыми, то вполне можно использовать такой подход для ее решения.
Специальные предложения
См. также
Регистры бухгалтерии. Общая информация 111
05.09.2019 6701 YPermitin 22
"Хочу универсально!" [Часть 1] 65
02.09.2019 4902 SeiOkami 35
Иерархия без "В ИЕРАРХИИ" 117
22.08.2019 4913 ildarovich 16
EnterpriseData – часть 3. Загрузка данных, идентификация объектов 62
22.08.2019 4231 ids79 7
Обработчики событий при записи объектов. Зачем и что за чем? 202
25.07.2019 12802 4 AlbinaAAA 23
Как проводятся документы в типовых конфигурациях от 1С 137
24.07.2019 16075 skv_79 32
FizzBuzz на 1С. Чем короче, тем веселее. Варианты принимаются... 8
24.07.2019 2864 vandalsvq 16
Управление качеством кода 136
22.07.2019 8233 Stepa86 29
Что делает "В ИЕРАРХИИ" в запросе? 94
16.07.2019 8183 YPermitin 34
Создание отчетов с помощью СКД - основные понятия и элементы 208
25.06.2019 20983 ids79 17
Реализуем Стек, Очередь и Приоритетную очередь в 1С 52
24.06.2019 7804 RonX01 63
Организация хранения промежуточных данных 3
29.05.2019 1954 scientes 1
Вычисление 200 тысяч знаков числа pi 73
28.05.2019 3983 Oleg_nsk 93
Регистры накопления. Виртуальные таблицы. Часть №1: Обороты 84
20.05.2019 11073 YPermitin 5
Даем названия переменным: как префиксы экономят наше время 10
06.05.2019 3214 Designer1C 69
Заметки по SQL: Срез последних - аналог запроса 15
15.01.2019 6318 IVC_goal 5
Разработка и сценарное тестирование с Vanessa-ADD. Концепция, теория и сквозной пример создания сценария 222
09.01.2019 27568 Vladimir Litvinenko 69
Многопоточное восстановление последовательностей 41
05.12.2018 7250 _ASZ_ 29
Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С 127
10.11.2018 22248 ids79 40
Основные понятия и механизмы оптимизации клиент-серверного взаимодействия в 1C 147
23.08.2018 22870 Rain88 42
Теорема номер тринадцать 15
15.03.2018 9358 vasilev2015 24
Введение в CI для 1С 87
21.11.2017 19332 real_MaxA 22
Как работает серверный вызов в 1С 459
18.11.2017 44247 pahich 77
#Область ВНЕШНИЕ_ВЫЗОВЫ или MVC в 1С, библиотечность и упрощение интеграции кода 43
12.10.2017 14810 for_sale 58
Групповая разработка конфигураций в крупном холдинге 68
15.08.2017 17545 stas_ganiev 15
Автоматизация процесса 1С-разработки 91
07.06.2017 23029 ekaruk 9
Пишем игру Минер. Обработка событий ActiveX в 1С 29
29.05.2017 12732 user621724_Dimav1979 11
Как я доступ на kb.1c.ru получал 91
01.05.2017 22536 ikekoval 33
Улучшение стандарта "Структура модуля" 6
26.03.2017 12325 o.nikolaev 23
"Распределение в запросе" или "избавляемся от перебора" 185
16.12.2016 28631 alexandersh 48
Планы обмена. Квитировать или гарантировать? 24
12.12.2016 14558 zhichkin 9
Некоторые принципы оптимизации запросов 1С (+SQL) 115
17.11.2016 8898 ture 40
Использование git для доработки типовых конфигураций 1С 230
11.10.2016 188459 pumbaE 31
Оптимизация запросов 1С:Предприятие – от теории к практике 116
07.10.2016 32080 bpc222 20
Регистры сведений 1С. Как это устроено. 729
05.08.2016 151050 Sergey.Noskov 155
Переводим расширения на 8.3.8. Памятка. 79
29.07.2016 39711 mrXoxot 12
Опыт практического применения методики BDD на 1С. Написание сценариев 121
03.07.2016 20335 oleynik.dv 132
Заметки про запросы. Последовательность. 110
27.05.2016 29631 vasilev2015 31
Оптимизация планирования доставки грузов. Алгоритм кластеризации k-means (метод K-средних). 26
10 стартмани
09.02.2016 26528 mi1man 4
Контур.EDI изнутри, или история командной разработки тиражного продукта на 1С 174
17.11.2015 36045 skif47 88
Порядок записи движений регистров при проведении документа 95
13.11.2015 80529 triton_tver 8
Три способа получить дерево элементов иерархического справочника 52
11.11.2015 63125 32ops 9
Распределение суммы по базе 48
08.11.2015 27732 starik-2005 19
Мультиинструментальный Brute Force 4
30.10.2015 10443 scientes 4
1С с "плюсами" 74
14.10.2015 19970 IntelInside 47
Знакомство с технологией Automation-сервер на примерах 33
28.09.2015 26193 niko11s 10
Критерии отбора 83
24.09.2015 49480 niko11s 13
По ссылке или по значению? Ключевое слово Знач и с чем его едят 196
12.08.2015 37186 Evil Beaver 239
Приемы обработки больших данных в 1С 258
07.08.2015 60324 tormozit 27