Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Автоприведение типа к базовому при присваивании. Возможно? (число прочтений - 5523 )
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Автоприведение типа к базовому при присваивании. Возможно?
18. Марта 2013 :: 09:41
Печать  
Уважаемые ГУРУ!

Корректное описание проблемы и постановка задачи здесь:
http://www.1cpp.ru/forum/YaBB.pl?num=1363599685/5#5
Цель (зачем это нужно и почему хочется): http://www.1cpp.ru/forum/YaBB.pl?num=1363599685/8#8
Временное решение здесь:
http://www.1cpp.ru/forum/YaBB.pl?num=1363599685/6#6
100% решения пока что нет.
------------------------------------------------------------------------------

Исходная теоретическая задача:

Есть класс "ОкопТипаСпрБ",  унаследован от "Справочник.Б" (только ОДИН предок)
Есть реквизит документа "Документ.В.РеквизитТипаСпрБ" типа "Справочник.Б"

Как красиво выполнить задачу:

Код
Выбрать все
Док = СоздатьДокумент("Документ.В");
Док.Найти...(...);
...
оКОП = СоздатьОбъект("ОкопТипаСпрБ");
оКОП.Найти...(...);
глПеременнаяТипаСпрБ = оКОП; // НЕ "оКОП.ТекущийЭлемент()" !!!
...
//вот здесь: не хочет выполнять "автоприведение типа к базовому"
//в то время как у КОП-а база ровно одна - того же типа что и реквизит документа
Док.РеквизитТипаСпрБ = глПеременнаяТипаСпрБ;
 



Вопрос:

В 1С++ такое возможно?
- если "да", то где мои грабли? + пример кода (плиз)
- если "нет" (предполагаю что, так): почему (на пальцах, пожалуйста)

Спасибо.

PS. Просьба не отправлять к Гради-Бучам, уже знакомы.
Просьба объяснить особенности реализации ООП
конкренто в 1С++: откуда ноги растут ? из-за чего ограничение...



« Последняя редакция: 19. Марта 2013 :: 11:00 - kos »  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #1 - 18. Марта 2013 :: 09:52
Печать  
оКОП - это всего лишь переменная с типом
оКОП.ТекущийЭлемент() - ссылка на конкретный объект в базе..

что не устраивает и что надо - хз.

ЗЫ: ну можешь переопределить метод ТекущийЭлемент() в своём копе - чтоб возвращал что-то еще (хотя что еще надо возвращать ? не ясно)
  
Наверх
 
IP записан
 
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #2 - 18. Марта 2013 :: 10:01
Печать  
Я расширяю функционал типового спр-ка "Справочник.Пользователи"
(перем глПользователь Экспорт)

Конструкцию типа:

Код
Выбрать все
Док.Автор = глПользователь; // нельзя менять на "глПользователь.ТекущийЭлемент()" 



не могу менять, т.к. поддержка при обновлениях сильно усложняется.

Как можно решить эту задачу,
написав код только один раз (расширив функционал классом)
не меняя все модули и печатные формы
при каждом обновлении?

Если переопределить метод "ТекущийЭлемент()":

Код
Выбрать все
функция ТекущийЭлемент() Экспорт
	возврат вирт().ПолучитьБазовыйКласс("Справочник.Пользователи").ТекущийЭлемент()
конецфункции
 



Всё равно не работает.
Есть идеи? Или почему нельзя.

Ведь если бы реквизит был типа "Строка"
и мы туда присвоим значение типа "Число" или "Справочник"
сработает приведение к типу строка
(будет установлено представление справочника или числа).....

ЗЫ: переменная "оКОП" это тоже ссылка (на адресное пространство)
с экземпляром класса "КОП", который в себе УЖЕ содержит экземпляр базового класса "Справочник" со ссылкой на данные в БД..
Как работает в 1С++ "ссылка из наследника на базу"?
Работает ли?
  
Наверх
 
IP записан
 
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #3 - 18. Марта 2013 :: 10:49
Печать  
Ситуация разъяснилась.Отвечу сам:

в оригинале типовой (работает)

Код
Выбрать все
Спр = СоздатьОбъект("Справочник.Пользователи");
Спр.НайтиЭлемент(....);
глПользователь = Спр.ТекущийЭлемент();//т.е действительно ИМЕННО ссылка
...
Док.Автор = глПользователь; //работает...
 



вариант без "ТекущийЭлемент" (не работает)

Код
Выбрать все
Спр = СоздатьОбъект("Справочник.Пользователи");
Спр.НайтиЭлемент(....);
глПользователь = Спр;//т.е объект типа "Справочник"
...
Док.Автор = глПользователь; //не работает, говорит:
// Неверное присвоение значения. Используйте: .ТекущийЭлемент()
 



т.е. такой способ "разруливания ссылок" реализуется самой 1С.....

Как быть? Вопрос остался:

Как переопределить переменную "глПользователь"
из справочника на "КОП" так,
чтобы не переписывать все модули и печатные формы?

Есть идеи?
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #4 - 18. Марта 2013 :: 11:04
Печать  
Не понял, чем текущийЭлемент не нравится ? И какая разница, где ты его будешь использовать - будь то родной справочник, будь то твой Коп-наследник от родного справочника.
У тебя же ничего не меняется в твоём случае, будь то

оКОП = СоздатьОбъект("ОкопТипаСпрБ");
оКОП.Найти...(...);
глПеременнаяТипаСпрБ = оКОП.ТекущийЭлемент(); //тут присвоил переменной ссылку на объект ИБ

или так

Спр= СоздатьОбъект("Справочник.Вася");
Спр.Найти...(...);
глПеременнаяТипаСпрБ = Спр.ТекущийЭлемент(); //тут присвоил переменной ссылку на объект ИБ

это два равнозначных кода - всего лишь переменной глПеременнаяТипаСпрБ  присвоится ссылка на объект ИБ.

  
Наверх
 
IP записан
 
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #5 - 18. Марта 2013 :: 11:42
Печать  
Помимо "типового" предназначения "Док.Автор = глПользователь"
эту же переменную использую для других целей (как "КОП").

Добавлять еще переменные в ГМ - не могу. Причин много.
Главная: при обновлениях слишком много правок нужно делать
(практически везде, где есть глПользователь)

Сама же переменная "глПользователь"
ПЕРЕОПРЕДЕЛЯЕТСЯ со справочника на "Коп"
при перехвате события "ПриНачалеРаботыСистемы()"

и в дальнейшем используется именно как "КОП" (singleton "МенеджерСеанса").

Поэтому мне нужно чтобы было именно

Код
Выбрать все
//в глобальном модуле
глПользователь = оКОП; // в целях МОЕЙ задачи недопустимо ХХХ.ТекущийЭлемент() !!!

// в форме документа должно остаться
Автор = глПользователь;// не трогаем типовую, т.е. ТекущийЭлемент() добавлять нельзя.
 



Проблема:
в реквизит документа "Автор" (типа "Справочник.Пользователи")
(с учетом ограничений написания кода, что в спойлере)
не устанавливается ссылка на текущий элемент БД "Справочник.Пользователи".
При этом переменная "глПользователь" - это КОП,
унаследованный от "Справочник.Пользователи"
(для простоты - пусть "Справочник.Пользователи" будет единственным базовым классом для указанного КОП-а)

Вопрос к power 1c++ users:

есть ли какой нить "хак",
чтобы выполнить подмену переменной "на лету"?

Вопрос к авторам 1С++:

Может есть смысл добавить 2 метода для перехвата ГМ
что-то типа (по аналогии с динамическими атрибутами)



(если Конт=0, то "ГлобальныйМодуль")


дабы можно было "на лету" подменять (переопределять)
переменные/атрибуты объекта/реквизиты формы ?

Кроме того, это решило бы еще одну задачку (проблему)
из темы "Доступ к глобальным переменным из КОП-ов"
(при условии загрузки 1cpp.dll до "ПриНачалеРаботыСистемы")
вот тема: http://www.1cpp.ru/forum/YaBB.pl?num=1363347562
а это баг (с 2008): http://www.1cpp.ru/bugs/show_bug.cgi?id=4216

Ведь основное предназначение ООП - это уменьшение "кодо-писания",
а получается замкнутый круг, когда
- нет доступа к глобальным переменным (у 1С++)
- нет возможности автоприведения типа к базовому (у самой 1С)

В конкретном данном случаем "самым базовым" является "ссылка на данные в БД":

Объект("МойКОП") -> Объект("Справочник") -> Объект(БД.ТекущийЭлемент())

Такую "подмену" я бы реализовал "вручную" при наличии указанных событий.
Или может у кого есть идеи как обойтись существующими средствами.
Плиз, поделитесь идеей.
« Последняя редакция: 19. Марта 2013 :: 10:58 - kos »  
Наверх
 
IP записан
 
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #6 - 18. Марта 2013 :: 12:39
Печать  
Кажется есть идея:

1) инициализируем "глПользователь"
при перехвате"ПриНачалеРаботыСистемы" нашим КОП-ом
(наследником от "Справочник.Пользователи")
как и ранее.

2) далее перехватываем и в обработчике повторно (на всякий случай)
переопределяем "глПользователь" на КОП методом "Сервис::УстановитьПеременнуюКонтекста()"
для каждого из событий:
- ВводНового
- ВводНаОсновании
- ПриОткрытии

3) в обработчике события "ПриЗаписи"
вместо "родного"
Док.Автор = глПользователь;
пишем:
Конт.Автор = глПользователь.ТекущийЭлемент();

Ход мыслей верный?
Прошу критиковать.  Круглые глаза

Правда, тут есть одно "НО":

что если в оригинальной форме контекста
помимо чтения переменной
будет сделано еще что-то с этой самой переменной?
Например, перепозиционирование на другой элемент?

Как это перехватить корректно ?


  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #7 - 18. Марта 2013 :: 15:12
Печать  
kos писал(а) 18. Марта 2013 :: 10:01:
Я расширяю функционал типового спр-ка "Справочник.Пользователи"
(перем глПользователь Экспорт)

Если переопределить метод "ТекущийЭлемент()":

Код
Выбрать все
функция ТекущийЭлемент() Экспорт
	возврат вирт().ПолучитьБазовыйКласс("Справочник.Пользователи").ТекущийЭлемент()
конецфункции
 



Всё равно не работает.

Что значит "не работает"? подробнее
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
kos
Full Member
***
Отсутствует


1C++ rocks!

Сообщений: 127
Местоположение: Киев
Зарегистрирован: 03. Марта 2013
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #8 - 18. Марта 2013 :: 18:04
Печать  
Я имел ввиду не "полиморфизм" или "наследование" не работает,
а именно "автоматическое приведение типов при присваивании"

при условии что код должен писаться именно в таком виде:

Код
Выбрать все
//в глобальном модуле
глПользователь = оКОП; // в целях МОЕЙ задачи недопустимо ХХХ.ТекущийЭлемент() !!!

// в форме документа должно остаться написание от ТИПОВОЙ конфигурации
Автор = глПользователь;// не трогаем типовую, т.е. ТекущийЭлемент() добавлять нельзя.
 



Я хотел добиться, чтобы при присваивании в реквизит документа объекта типа КОП
когда базовый тип КОП-а и тип реквизита совпадают
(в данном случае слева и справа мы имеем "Справочник.Пользователи")
не нужно было указывать "ТекущийЭлемент()"

Зачем (цель):

При поддержке ТИПОВОЙ 77, где повсеместно написано именно

Автор = глПользователь;//т.е. без .ТекущийЭлемент()

если я заменю переменную глПользователь своим КОП-ом,
тогда при каждом обновлении типовой 77
КАЖДЫЙ РАЗ ручками во всех модулях и печатных формах
где есть глПользователь
придется заниматься рефактирингом по написанию "хвоста" '.ТекущийЭлемент()'

Достаточно утомительно такое бестолковое кодо-писание.

Не находите?

Поэтому и предлагаю

иметь механизм подмены значений переменных на-лету

чтобы можно было в ОДНОМ месте выполнить подмену (перехватив событие чтение/запись значения):
- при чтении : в оригинальном модуле "Автор=глПользователь;"
перехватом выполнить это "КонтФормы.Автор=глПользователь.ТекущийЭлемент();"
- при записи : в оригинальном модуле  "глПользователь = Автор;"
перехватом выполнить это "глПользователь.УстановитьАвтора(КонтФормы.Автор);"

где глПользователь - в реальности: это КОП, а не "Справочник.Пользователи" (унаследованный от этого справочника)

Идет речь не о замене текста модуля формы/глобального модуля,
а именно перехват события чтения\записи значения в некотором ГМ или ГК Контексте.

PS. ще один "+": кроме того, такой "финт" позволит приблизить 77 к 8-ке
в том смысле, что(в дополнение к "РасширениеФормы")
это позволит "навешивать" СВОИ обработчики событий НА РЕКВИЗИТЫ контекста формы
Смех
« Последняя редакция: 19. Марта 2013 :: 11:25 - kos »  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Автоприведение типа к базовому при присваивании. Возможно?
Ответ #9 - 19. Марта 2013 :: 04:01
Печать  
У меня возникала подобная же проблема:
ноги конфы растут из стандартного ПУБа, есть переменная глПользователь, которая используется для всяких конт.Автор = глПользователь.
Сделал глПользователя объектом класса ТСправочник.Пользователи - все сломалось.
В конечном итоге, все пришлось менять на конт.Автор = глПользователь.ТекущийПользователь() (где ТекущийПользователь() - специальный метод, по сути возвращающий ТекущийЭлемент(), но с кешированием).
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать