Наследование и скрипты

отредактировано November 2008 Раздел: FastReport 4.0
Всем доброе время суток.

Столкнулся с такой проблемой:

Есть отчет-родитель, в нем бэнды поля и т.д. В отчете есть определенные скрипты.
Есть отчет наследник, в нем все это наследуется.

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

Что посоветуете сделать в данной ситуации?

Комментарии

  • stan5stan5 Новошахтинск
    отредактировано 06:42
    О Вашей ситуации прямо написано в руководстве пользователя FR4- стр. 202 pdf (стр. 196 пп 12.1):

    "... Только помните о следующем: если вы поменяли какое-то свойство (к примеру, цвет) у объекта с замком - оно сохранится в данном экземпляре отчета и изменения в базовом отчете его уже не коснутся. Например: в базовом отчете объект был белым, а в наследованном отчете вы поменяли его цвет на красный. Если теперь зайти в базовый отчет и поменять цвет объекта на зеленый, в наследованном отчете он останется красным. Если бы мы не меняли цвет на красный, то изменение цвета в базовом отчете отразилось бы и на наследованном. Это же касается и текста, и размеров\расположения, и любого другого свойства объекта."

    Логика основана на том, чтобы изменения в наследованном отчете не затирались потом изменениями в базовом, которые касаются этого же элемента.

    Выход из ситуации - после изменений в наследованном отчете сделать его, в свою очередь, базовым и создать его потомков - какие нужны.
  • отредактировано 06:42
    Механизм этой "фичи" понятен. И как так получается, тоже понятно. Но правильный ли он с точки зрения здоровой логики ООП? Одно дело наследовать свойства объектов, а другое - функционал отчета, если логика его работы реализована в скриптах. Какое же это наследование? Недонаследование какое-то.
    Формы в Delphi можно наследовать. И свойства компонентов у наследников можно переназначать. Но ФУНКЦИОНАЛ формы как класса НАСЛЕДУЕТСЯ. И если требуется изменить работу формы в ее базовом классе, то проблем с этим не возникает.
    А что мы видим при "наследовании" отчета? Допустим, добавляю в базовый шаблон обработчик какого-нибудь события. В отчете-наследнике у унаследованного объекта унаследовано и название обработчика. Вроде, логично. Но в скрипте его, естественно, нет (потому, что в свое время у наследованного отчета нужно было реализовать свой функционал и скрипт наследника "накрыл" собой скрипт базового отчета). Это понятно, взяться ему там неоткуда. Наследованный отчет молча отрабатывает, игнорируя такую нестыковочку. Никто никогда не узнает, что в базовом отчете поменялся функционал. Да и вызвать что-то типа inherited нельзя - FastScript просто не умеет этого делать. Он процедурно-ориентированный. Хотя доработать его, я думаю можно. Отработать ключевое слово "inherited", пройдясь по пулу всех скриптов отчетов предков.
    Господа разработчики, я думаю, что пробел в механизме наследования отчетов очень серьезный. Чем крыть будете?
  • stan5stan5 Новошахтинск
    отредактировано 06:42
    Согласен с Uncle AU - дорабатывать механизм наследования нужно. Ждем. А пока выходим из ситуации имеющимися средствами и способами.
  • отредактировано 06:42
    stan5 написал: »
    О Вашей ситуации прямо написано в руководстве пользователя FR4- стр. 202 pdf (стр. 196 пп 12.1):

    "... Только помните о следующем: если вы поменяли какое-то свойство (к примеру, цвет) у объекта с замком - оно сохранится в данном экземпляре отчета и изменения в базовом отчете его уже не коснутся. Например: в базовом отчете объект был белым, а в наследованном отчете вы поменяли его цвет на красный. Если теперь зайти в базовый отчет и поменять цвет объекта на зеленый, в наследованном отчете он останется красным. Если бы мы не меняли цвет на красный, то изменение цвета в базовом отчете отразилось бы и на наследованном. Это же касается и текста, и размеров\расположения, и любого другого свойства объекта."

    Логика основана на том, чтобы изменения в наследованном отчете не затирались потом изменениями в базовом, которые касаются этого же элемента.

    Выход из ситуации - после изменений в наследованном отчете сделать его, в свою очередь, базовым и создать его потомков - какие нужны.
    :-)
    Ситуация ясна. Буду дописывать данный кусок наследования.
    ЗЫ: про документацию знаю и в данном контексте цитата увожаемого stan5 звучит забавно. Если мы говорим об объекте, то мы подразумеваем что под озвученное правило подподяют не только свойства, но и процедуры обработки событий. А на практике получается, что если любой скрипт в отчете поменяли (вне зависимости от принадлежности к определенному объекту) то замещается не конкретная процедура и даже не скрипты по затронотуму объекту а весь "скрипт" отчета. И если в базовом отчете поменяли скрипт совсем другого объекта, то он таки в наследник и не попадет. Т.е. реальность и документация немного расходятся. :-)
    ...
    А, вообще, наследование штука классная. Овнеру данной фичи большой респект ;-)
    ТО Uncle AU: в преферанс играете? :-) Как видите реализацию inherited?
  • отредактировано 06:42
    Вижу, что надо при считывании отчета из потока накапливать все скрипты от прародителей в список. И при работе отчета выполнять обработчик события (ну или процедуру/функцию) из того скрипта, который при проходе по списку (от детей к родителям) попадется первым.
    Еще вижу, что надо сделать в FS обработку ключевого слова inherited. При его использовании анализируй тот же список, но начиная с родителя. По-моему, это будет самое сложное место.
    Вижу, что если обработчик не найден, надо все-таки ругнуться.
    Ну и вижу, что дизайнер придется доработать, чтобы показать эти унаследованные скрипты. А при двойном клике в инспекторе на свойстве события попадать в нужный скрипт (найдя все по тому-же алгоритму скрипт с ближайшей реализацией обработчика).

    Что-то разработчики ничего не хотят сказать. Ответьте народу, хочется услышать компетентное мнение.
  • отредактировано November 2008
    написал:
    Вижу, что надо при считывании отчета из потока накапливать все скрипты от прародителей в список. И при работе отчета выполнять обработчик события (ну или процедуру/функцию) из того скрипта, который при проходе по списку (от детей к родителям) попадется первым.
    Еще вижу, что надо сделать в FS обработку ключевого слова inherited. При его использовании анализируй тот же список, но начиная с родителя. По-моему, это будет самое сложное место.
    Вижу, что если обработчик не найден, надо все-таки ругнуться.
    А что этот список даст ?
    Сказать честно я не представляю себе как это должно работать.

    Допустим в скрипте есть inherited, и что должно происходить при его выполнении, вызываться метод предка, какого, откуда, откуда сприпт должен определить наследником чего именно является этот метод ?
    Искать функции в списке предков функцию с таким же именем не очень хороший вариант(такой вариант можно сделать с минимальным кол-вом изменений, но это будет скорее как доработка Репорта , а не скрипта).

    Тут нужно подходить с другой стороны, и пример далеко искать не нужно, достаточно взглянуть на реализацию rtti в Delphi :)
    Для начала в с скрипте нужно разделить понятия класса и объекта, которые по сути сейчас являются одним и тем же.
    Т.е. класс должен содержать таблицу верт. функций и таблицу членов данного класса(имя и тип), а объект должен хранить сами члены класса(значения) и конечно ссылку на класс.

    После этого уже будет не сложно добавить возможность описания классов c возможностью наследования в скрипте.
    написал:
    Ну и вижу, что дизайнер придется доработать, чтобы показать эти унаследованные скрипты. А при двойном клике в инспекторе на свойстве события попадать в нужный скрипт (найдя все по тому-же алгоритму скрипт с ближайшей реализацией обработчика).
    Дизайнер в это случае придется практически полностью переделывать.

    Конечно в подобной реализации есть свои "затыки" :)
  • отредактировано 06:42
    написал:
    Искать функции в списке предков функцию с таким же именем не очень хороший вариант(такой вариант можно сделать с минимальным кол-вом изменений, но это будет скорее как доработка Репорта , а не скрипта).
    Да, именно это я и имел ввиду. TList с элементами TfsScript. Но чем он плох на данном этапе? Малой кровью можно доработать механизм наследования, чтобы появилась реальная возможность наследования функционала.
    Слово inherited лишь означало бы, что вызываемую функцию надо начинать искать со скрипта предка и при необходимости спускаться глубже. Если после inherited стоит имя конкретной функции, то ищем ее. Если стоит ";", то ищем функцию с именем функции контекста и передаем те же параметры.
    написал:
    Для начала в с скрипте нужно разделить понятия класса и объекта, которые по сути сейчас являются одним и тем же.
    Т.е. класс должен содержать таблицу верт. функций и таблицу членов данного класса(имя и тип), а объект должен хранить сами члены класса(значения) и конечно ссылку на класс.
    Это уже серьезная доработка FastScript-а и он уже превратиться в объектно-ориентированный. Оно конечно-же хорошо, только, боюсь, что ждать долго придется.
  • отредактировано 06:42
    uncle AU написал: »
    Да, именно это я и имел ввиду. TList с элементами TfsScript. Но чем он плох на данном этапе? Малой кровью можно доработать механизм наследования, чтобы появилась реальная возможность наследования функционала.
    Слово inherited лишь означало бы, что вызываемую функцию надо начинать искать со скрипта предка и при необходимости спускаться глубже. Если после inherited стоит имя конкретной функции, то ищем ее. Если стоит ";", то ищем функцию с именем функции контекста и передаем те же параметры.
    Список в данном случае не нужен, отчет предок сохраняется в ParentReport, из него же можно взять и скрипт.
    Только простая компиляция скрипта предка ничего не даст, т.к. при загрузки шаблона FR просто копирует объекты из отчета предка в текущий отчет, а скрипт будет ссылаться на объекты отчета из ParentReport.
    Как выход добавить поле для хранения скрипта предка, копировать в него текст скрипта и добавлять все наследованные объекты из текущего отчета(все это нужно делать в момент построения отчета).
    Обработку Inherited в скрипте в данным случае придется делать через событие, т.к. скрипт и отчет два разных компонента.

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

    uncle AU написал: »
    Это уже серьезная доработка FastScript-а и он уже превратиться в объектно-ориентированный. Оно конечно-же хорошо, только, боюсь, что ждать долго придется.
    Подобная доработка возможно появится в FR5.
  • отредактировано 06:42
    Ден, Вы меня без ножа зарезали.
    написал:
    FR поддерживает только один уровень наследования
    Что Вы имеете ввиду? Нельзя наследовать отчет от того, кто уже сам наследник? Конечно же я ринулся проверять это утверждение. Но, кажется, (на первый взгляд) наследник 2-го уровня все-таки загрузил "дедушку". Но зерно сомнений, что что-то там может быть не так, Вы посеяли.
  • отредактировано 06:42
    Спасибо -=Den=-, stan5 и uncle AU за внимание к моей проблеме.
    Начинаю делать наследование по схеме uncle AU с небольшими своими изменениями. Уж больно не наглядно получается, куда-то кликаем, чего-то открывается ...
    Картина, в принципе, ясна, только есть одно но:
    При реализации ключевого слова inherited [назовем это пока так :-)] я отойду от основного проекта FR. Т.к. рано или поздно придется переходить на новую версию и мне нужно будет сливать функционал, то хотелось бы решить это малой кровью. т.е. будет 2-а плана: FR реализует требуемый функционал и мне прийдется отключать свои костыли и перехадить на нативный бренч; FR не реализует то что мы тут бурно обсуждаем и собсна сабж. В любом из исходов меня ждут траблы различной степени тяжести :-). Если есть время\желание поделитесь опытом как спроектировать доработки так, чтоб потом жилось спокойно.
    ...
    ЗЫ: В св-ве ParentReport нашел только имя самого отчета .... может не там смотрю.
  • отредактировано November 2008
    написал:
    Ден, Вы меня без ножа зарезали.
    Сейчас буду реанимировать :)

    Я не так выразился правильней было бы сказать : есть некоторые особенности которые в основном проявляются при наследовании нескольких отчетов(хотя оно не работает и при наследовании от одного шаблона :) ).
    Некоторые объекты пишут данные в PropData в бинарном виде (TfrxChartView например), так вот если Вы к примеру хотите сделать отчет с чартом и в одном из потомков поменяли св-во относящиеся к чарту, то все остальные св-ва уже наследоваться не будет.
    Аналогичная ситуация и с внутренними компонентами доступа к данным.
    Ну и конечно не стоит забывать что поменяв любое св-во в потомке, дочерние отчеты будут наследовать именно его, даже если в базовом отчете выставить аналогичное значение(а потом пробовать его изменить ... и некоторые так делают, а потом пишут вот у меня наследование не работает :) ).


    backorange

    Я хотел сказать FParentReportObject :)

    В Вашем случае можно все сделать даже не трогая FS:
    - Добавить репорту функцию InheriteCall (к примеру).
    - добавить поле FParentScript, создавать его так же как и FParentReportObject
    - копировать текст скрипта из FParentReportObject.Script
    - при выполнении скрипта (PrepareScript у Tfrxreport) добавить все объекты с флагом Ancestor в FParentScript(делать это придется в цикле, пробежать по всем FParentScript, .т.е. ParentS := FParentScript; while ParentS <> nil do begin ParentS := FParentReportObject.FParentScript; .. итд ).
    - в Report.InheriteCall вызывать функцию с таким же именем (или добавить параметр в которой указывать имя функции) из FParentScript.

    Конечно дизайнер придется переделывать, лучшем вариантом тут будет сделать редактор скрипта на вкладках, которые будут открываться по мере необходимости.

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

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.