Переключение на Главную Страницу Страницы: [1] 2  ОтправитьПечать
Горячая тема (более 10 ответов) ДобавитьДинамическоеСвойство() в базовом классе (число прочтений - 14691 )
mash
1c++ donor
Отсутствует


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
ДобавитьДинамическоеСвойство() в базовом классе
13. Октября 2008 :: 08:18
Печать  
В связи с новыми веяниями по реализации динамических атрибутов - переделываю уже существующие классы, и столкнулся с такой ситуацией.

Метод Сам(Контекст).ДобавитьДинамическоеСвойство() реализован в базовом классе, а _ПриЧтенииСвойства в классе-наследнике.
В этом случае, при инициализации никаких ошибок нет, однако при попытке работать с динамическими атрибутами возникает исключение - "Поле агрегатного объекта не обнаружено"

При перемещении методов _ПриЧтенииСвойства  и _ПриЗаписиСвойства в базовый класс (что вроде бы должно являться правильным, в соответствии с ветками этого форума) - исключение возникает в момент инициализации класса - попытки добавления динамического атрибута (ругается на отстутствие реализации указанных методов в классе). Я так понял эти методы должны быть реализованы в классе-наследнике ? Добавление публичности (через Экспорт) результата не дает.

И лишь один вариант (когда динамические атрибуты и добавляются и обрабатываются в классе-наследнике) исключений не дает, и работает как надо. Только с точки зрения ООП - он совсем не интересен  Печаль

У меня вопрос, это глюк или фича ? Потому что если это фича, то такая фича нам не нужна  Печаль  Ибо динамические свойства полностью утратили гибкость.

Версия компоненты 2.5.0.7 (рекомендованная)
  

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #1 - 14. Октября 2008 :: 04:38
Печать  
mash писал(а) 13. Октября 2008 :: 08:18:
Метод Сам(Контекст).ДобавитьДинамическоеСвойство() реализован в базовом классе, а _ПриЧтенииСвойства в классе-наследнике.
1. В этом случае, при инициализации никаких ошибок нет, однако при попытке работать с динамическими атрибутами возникает исключение - "Поле агрегатного объекта не обнаружено"

2. При перемещении методов _ПриЧтенииСвойства  и _ПриЗаписиСвойства в базовый класс (что вроде бы должно являться правильным, в соответствии с ветками этого форума) - исключение возникает в момент инициализации класса - попытки добавления динамического атрибута (ругается на отстутствие реализации указанных методов в классе). Я так понял эти методы должны быть реализованы в классе-наследнике ?

По пунктам:
1. Все верно, так и должно быть. Где создаешь динам.свойства, там их и обрабатывай
2. Также все верно.
Метод ДобавитьДинамическоеСвойство() не работает через Сам() или вирт() для классов, в которых нет спец.методов ПриЧтенииСвойства и _ПриЗаписиСвойства.
Этот метод можно вызвать только внутри модуля, которые реализует работу с динамическими свойствами.
Это ограничение сделано специально для обеспечения безошибочной работы механизма работы со свойствами. Оно описано в документации.

Для его преодоления и использования в цепочке наследования можешь в базовом классе сделать некий интерфейс по работе с его динамическими свойствами.

Т.е. в базовом классе есть наследуемые методы
ДобавитьСвойство(...) Экспорт - код этого метода вызывает ДобавитьДинамическоеСвойство
ПриЧтенииСвойства(...) Экспорт
ПриЗаписиСвойства(...) Экспорт - эти 2 метода вызываются из соответствующих обработчиков _ПриХХХ через Сам().

Данные методы уже можно переопределять/вызывать из наследника и вызывать из любого клиента. И тогда разработчик сам отвечает за работу данного механизма, соответствие свойств и т.п.
  

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


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #2 - 14. Октября 2008 :: 07:48
Печать  
Ага, вот оно как  Улыбка Неочевидно...

Разобрался, конечно, спасибо. Только вот метод
Код
Выбрать все
Процедура ДобавитьСвойство(_ИмяСвойства) Экспорт
	Сам(Контекст).ДобавитьДинамическоеСвойство(_ИмяСвойства);
КонецПроцедуры
 


должен быть в каждом классе наследнике (хотя вызываться он, конечно, может из обобщенных методов базового класса), также как и _ПриЗаписиСвойства() и _ПриЧтенииСвойства() (которые в каждом классе-наследнике вызывают одинаковые методы базовых классов).

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

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #3 - 14. Октября 2008 :: 08:28
Печать  
mash писал(а) 14. Октября 2008 :: 07:48:
Разобрался, конечно, спасибо. Только вот метод
Код
Выбрать все
Процедура ДобавитьСвойство(_ИмяСвойства) Экспорт
	Сам(Контекст).ДобавитьДинамическоеСвойство(_ИмяСвойства);
КонецПроцедуры
 


должен быть в каждом классе наследнике (хотя вызываться он, конечно, может из обобщенных методов базового класса), также как и _ПриЗаписиСвойства() и _ПриЧтенииСвойства() (которые в каждом классе-наследнике вызывают одинаковые методы базовых классов).

С чего ты это решил по поводу "в каждом классе-наследнике" ?
Этот метод есть в базовом классе, больше его нигде не нужно переопределять, кроме тех классов-наследников, которые сами работают со своими динамическими свойствами.
  

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


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #4 - 14. Октября 2008 :: 12:30
Печать  
потому что, если код
[code]
Сам(Контекст).ДобавитьДинамическоеСвойство(_ИмяСвойства);
[/code]
будет расположен в модуле [b]базового[/b] класса, то при попытке работы с динамическими свойствами у меня выдается [i]"Поле агрегатного объекта не обнаружено"[/i].
а вот если я пишу в [b]наследнике[/b]
[code]
Процедура ДобавитьСвойство(_ИмяСвойства) Экспорт
     Сам(Контекст).ДобавитьДинамическоеСвойство(_ИмяСвойства);
КонецПроцедуры
[/code]
а в конструкторе [b]базового [/b] класса вызываю
[code]Сам(Контекст).ДобавитьСвойство(_имясвойства)[/code]
, то все ok
  

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #5 - 14. Октября 2008 :: 12:35
Печать  
artbear писал(а) 14. Октября 2008 :: 08:28:
mash писал(а) 14. Октября 2008 :: 07:48:
Разобрался, конечно, спасибо. Только вот метод
Код
Выбрать все
Процедура ДобавитьСвойство(_ИмяСвойства) Экспорт
	Сам(Контекст).ДобавитьДинамическоеСвойство(_ИмяСвойства);
КонецПроцедуры
 


должен быть в каждом классе наследнике (хотя вызываться он, конечно, может из обобщенных методов базового класса), также как и _ПриЗаписиСвойства() и _ПриЧтенииСвойства() (которые в каждом классе-наследнике вызывают одинаковые методы базовых классов).

С чего ты это решил по поводу "в каждом классе-наследнике" ?
Этот метод есть в базовом классе, больше его нигде не нужно переопределять, кроме тех классов-наследников, которые сами работают со своими динамическими свойствами.

Еще раз - этот метод должен переопределяться только в тех классах-наследников, которые сами работают со своими динамическими свойствами, т.е. сами добавляют свойства.
Если у тебя все класс-наследники такие, тогда, конечно, так должно быть во всех этих классах.
  

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


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #6 - 14. Октября 2008 :: 13:05
Печать  
Я просто может чего не совсем понимаю, но скажи пожалуйста, где должны быть расположены реализации методов _ПриЗаписиСвойства() , _ПриПолученииСвойства() и вызов метода ДобавитьДинамическоеСвойство() - в базовом классе, или в классе наследнике. Предложенная парой постов выше схема когда ДобавитьДинамическоеСвойство() расположено в базовом классе, а _ПриЗаписиСвойства() , _ПриПолученииСвойства() реализованы в наследниках - не работает.
Цитата:
Поле агрегатного объекта не обнаружено.
Вот ее диагноз.

Если убрать _ПриЗаписиСвойства() и _ПриПолученииСвойства() из наследника в базовый класс - перестает работать ДобавитьДинамическоеСвойство(), расположенное в базовом классе,  с ошибкой
Цитата:
КОП::ДобавитьДинамическоеСвойство: в классе должны быть реализованы соответствующие методы _ПриЧтенииСвойства и _ПриЗаписиСвойства


В настоящее время работает лишь один вариант - когда реализации методов _ПриЗаписиСвойства() , _ПриПолученииСвойства() и вызов метода ДобавитьДинамическоеСвойство() расположены в каждом из наследников. А базовый класс вызывает методы классов-наследников для добавления динамических свойств.

Есть вариант, совсем как бы, неправильный это реализация методов _ПриЧтенииСвойства и _ПриЗаписиСвойства и в базовом классе и в наследнике. Тогда вызов Сам(Контекст).ДобавитьДинамическоеСвойство() можно вызывать и из методов базового класса.

Я предполагал, изначально, что можно будет реализовать всю механнику работы с динамическими свойствами (их добавление, запись и чтение) в базовом классе, а в классах наследниках вообще не парится на эту тему.
  

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
mash
1c++ donor
Отсутствует


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #7 - 14. Октября 2008 :: 13:30
Печать  
Я поясню свою задачу, чтобы было понятнее.

У меня есть класс Регистры. Он реализует определенные действия с регистрами. И у этого базового класса - есть наследники. Каждый по виду конкретного регистра. Единственный метод определенный в каждом классе - наследнике Вид(), который вызывается из базового класса.

До глобальной революции с динамическими атрибутами - в базовом классе у меня заполнялась структура с измерениями и ресурсами, а в наследниках были определены только методы _ПриЗаписиСвойства и _ПриЧтенииСвойства которые вызывали определенные методы базового класса по чтению/записи полей структуры. Что не очень красиво, но единственно, на тот момент, возможно.

В результате революции, я как бы ожидал, что и методы работы с динамическими свойствами можно будет упрятать в базовый класс, и схема, наконец засияет красотой и простой. В каждом наследнике будет по 3 строки кода Улыбка Но не судьба. Оказывается - теперь мне надо в каждом наследнике реализовывать три метода _ПриЧтенииСвойства, _ПриЗаписиСвойства и ДобавитьСвойство() Экспорт. Получилось не упрощение схемы и кода, а наоборот логическое усложнение.
  

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #8 - 14. Октября 2008 :: 13:43
Печать  
Я понял твою задачу, подумаю насчет реализации.
Возможно, что ты где-то неправ, возможно, я в своих утверждениях Печаль
Мне самому нравится реализация только в базовых классах, именно она и запланирована.

ЗЫ тестовую конфу с регистрами можешь сделать ?
  

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


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #9 - 14. Октября 2008 :: 14:25
Печать  
Тестовую - именно чтобы регистры были реализованы, или просто на проверку и демонстрацию механизма обработки динамическим аттрибутов ?

Если второе, то она в приложении.
  

DynAttr.zip ( 12 KB | Загрузки )

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #10 - 16. Октября 2008 :: 04:17
Печать  
В общем, все оказалось просто Улыбка
Т.е. делаем ту же схему, что я описал выше http://www.1cpp.ru/forum/YaBB.pl?num=1223885925/1#1

Одно НО - в базовом классе нужно писать немного по-другому, без использования контекста наследника
Цитата:
Процедура ДобавитьСвойство(_ИмяСвойства) Экспорт
     я().ДобавитьДинамическоеСвойство(_ИмяСвойства);
КонецПроцедуры

В базовый же класс вставляем методы _ПриЧтенииСвойства(Имя) и _ПриЗаписиСвойства(Имя,Значение)
И далее, как я описал Улыбка

Выкладываю твой же пример, исправленный мной.
Жду комментариев.

ЗЫ мои правки обозначены в комментах как Артур.
  

DynamicAttribs_artbear.rar ( 11 KB | Загрузки )

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


1C++ v. 3.0.1.23

Сообщений: 148
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #11 - 16. Октября 2008 :: 08:11
Печать  
ага, вот теперь все понятно. Полное следование заветам ООП про наследование.
Единственное неочевидность использования я() для работы с динамическими свойствами, я то по старинке пользовалься контекстом через Сам(контекст).

Для информации - тем кто наступит на те же грабли. Для добавления динам. свойств в базовом классе делаем

Код
Выбрать все
я().ДобавитьДинамическоеСвойство(ИмяСвойства) 



, вместо

Код
Выбрать все
Сам(Контекст).ДобавитьДинамическоеСвойство(ИмяСвойства) 


который в базовых классах не работает  Круглые глаза
  

Поспешность наносит ущерб
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #12 - 16. Октября 2008 :: 08:32
Печать  
mash писал(а) 16. Октября 2008 :: 08:11:
ага, вот теперь все понятно. Полное следование заветам ООП про наследование.
Единственное неочевидность - использование я() для работы с динамическими свойствами, я то по старинке пользовалься контекстом через Сам(контекст).

Для информации - тем кто наступит на те же грабли. Для добавления динам. свойств в базовом классе делаем

Код
Выбрать все
Я().ДобавитьДинамическоеСвойство(ИмяСвойства) 



, вместо

Код
Выбрать все
Сам(Контекст).ДобавитьДинамическоеСвойство(ИмяСвойства) 


который в базовых классах не работает  Круглые глаза

Небольшое уточнение Улыбка
вместо "который в базовых классах не работает" ИМХО правильнее нужно сказать "который не работает при вызове данного метода базового класса из модулей классов-наследников"
« Последняя редакция: 16. Октября 2008 :: 10:37 - artbear »  

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


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

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #13 - 17. Октября 2008 :: 04:49
Печать  
Обновил доку по icpp для указания тонкого момента с Я()

В общем, рекомендация - всегда вызывайте КОП::ДобавитьДинамическоеСвойство() через Я()

В этом случае ошибок не будет ни в одиночном или базовом классе, ни в его классах наследниках.
  

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



Сообщений: 1599
Местоположение: г.Новокузнецк
Зарегистрирован: 21. Февраля 2007
Пол: Мужской
Re: ДобавитьДинамическоеСвойство() в базовом классе
Ответ #14 - 28. Октября 2008 :: 06:19
Печать  
artbear писал(а) 17. Октября 2008 :: 04:49:
Обновил доку по icpp для указания тонкого момента с Я()

В общем, рекомендация - всегда вызывайте КОП::ДобавитьДинамическоеСвойство() через Я()

В этом случае ошибок не будет ни в одиночном или базовом классе, ни в его классах наследниках.


Т.е. при использовании Сам(Контекст) нельзя вызывать метод базового класса в котором добавляются динамические свойства?
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать