четверг, 6 августа 2015 г.

Коротко. Переопределение слов

По мотивам - Коротко. Сделал чудную штуку - переопределение слов

Вот такое сделал:

REDEFINITION
 STRING FUNCTION ToPrintable
   IN aValue
  if ( aValue IsArray ) then
   ( [ '[ ' for aValue ( @SELF DO ) ' ]' ] ' ' strings:CatSep >>> Result )
  else 
   ( aValue inherited >>> Result )
 ; // ToPrintable

Раньше массивы не печатались, а теперь печатаются.

А можно ещё сделать так:

REDEFINITION
 STRING FUNCTION ToPrintable
   IN aValue
  if ( aValue IsObject ) then
   (
    if ( aValue IS class:TComponent ) then
     (
       [ aValue pop:Component:Name ':' aValue pop:object:ClassName ]
        strings:Cat >>> Result
     )
    else
     ( aValue pop:object:ClassName >>> Result )
   )
  else 
   ( aValue inherited >>> Result )
 ; // ToPrintable


Теперь ещё и объекты "печатаются".

Виртуальность, без виртуальности. REDEFINITION'ы "нанизываются" друг на друга как "обработчики прерываний", ну или как "хуки".

Один REDEFINITION декорирует другой.

Там правда с порядком вызова есть "тонкости" - СНАЧАЛА надо REDEFINITION для IsObject, а ТОЛЬКО ПОТОМ - для IsArray.

Чтобы рекурсия работала правильно.

А если нужна "реальная виртуальность", то можно вклинить и виртуальность.

Позже напишу как.

Ну в общих словах пока так:

REDEFINITION
 STRING FUNCTION ToPrintable
   IN aValue
   PUBLIC STATIC VAR g_ToPrintable = inherited
   // - тут запоминаем ссылку на inherited
  aValue g_ToPrintable DO >>> Result
  // - тут выполняем то, что лежит в ссылке
  //   Ну и понятно, что "позже" эту ссылку можно переопределить
  // Таким образом:

  // ... в ДРУГОМ месте кода где-то ...
  // Пишем следующее:

  STRING FUNCTION ClassToPrintable
   IN aValue

   VOID IMMEDIATE OPERATOR CompileCallToPrintable
    ToPrintable :: g_ToPrintable CompileValue @ DO CompileValue
    // - тут компилируем вызов по ссылке того, что лежит в g_ToPrintable
   ; // CompileCallToPrintable

   if ( aValue IsObject ) then
    (
     if ( aValue IS class:TComponent ) then
      (
        [ aValue pop:Component:Name ':' aValue pop:object:ClassName ]
         strings:Cat >>> Result
      )
     else
      ( aValue pop:object:ClassName >>> Result )
    )
   else 
    ( aValue CompileCallToPrintable >>> Result )
  ; // ClassToPrintable
 
  ToPrintable :: g_ToPrintable := ClassToPrintable 
  // - тут переопределили ссылку
  // Ну и дальше опять же - рекурсивно по цепочке
  // Вот так:

  STRING FUNCTION ArrayToPrintable
    IN aValue
   if ( aValue IsArray ) then
    ( [ '[ ' for aValue ( @SELF DO ) ' ]' ] ' ' strings:CatSep >>> Result )
   else 
    ( aValue CompileCallToPrintable >>> Result )
  ; // ArrayToPrintable

  ToPrintable :: g_ToPrintable := ArrayToPrintable 
  // - тут переопределили ссылку

 ; // ToPrintable

Зачем всё это?

Это всё нужно для доопределения грамматики и трансформирования предметной области.

Там где невозможно менять "проектные классы".

Например для тестировщиков.

Ну а о том как менять проектные классы (типа делать АОП - Агентно-ориентированный подход и Аспектно-ориентированное программирование) я напишу позже.

Вообще говоря все эти REDEFINITION'ы и нужны для того, чтобы ДООПРЕДЕЛЯТЬ "аспекты". Которые не УКЛАДЫВАЮТСЯ в "сквозную иерархию" проектных классов.

Они - СБОКУ, от иерархии наследования.

Ну и понятно, что это всё не для "конечного пользователя", а лишь для тех кто хочет и МОЖЕТ доопределять грамматику.

Ремарка:

 strings:Cat - складывает строки в массиве
 strings:CatSep - складывает строки в массиве через разделитель
 @SELF DO - рекурсивно вызывает "себя же"
 CompileValue - компилирует ссылку на слово

Всё описанное реализует собой парадигму "контрольных точек".

(+) О тестах и специально оборудованных "контрольных точках"
(+) Коротко. Ни о чём. Инверсия зависимостей
(+) Коротко. Продолжение про инверсию зависимостей
(+) Коротко. О блоге, стиле написания статей и ведении полемики
(+) Депрессия. Или превратности hResult и прочих ErrorCode

Комментариев нет:

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