Перейти к основному содержимому
Версия: 5.x

Расширение действий

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

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

Расширение действий позволяет:

  • Реализовывать концепцию полиморфизма действий по аналогии с некоторыми объектно-ориентированными языками программирования.
  • Убирать зависимость между модулями, путем добавления определенных "точек входа", в которые можно позднее добавлять новое поведение.

Полиморфная форма

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

Взаимоисключаемость условий

Как и для оператора ветвления, для абстрактного действия можно указать, что все его условия должны быть взаимоисключающими. Соответственно, если эта опция указана, а условия не являются взаимоисключающими, платформа выдаст соответствующую ошибку.

Стоит отметить, что такая проверка является не более чем подсказкой платформе (для лучшей оптимизации) и определенным самоконтролем со стороны разработчика. Однако, при этом использование такой проверки позволяет во многих случаях сделать код более прозрачным и читабельным (особенно в полиморфной форме абстрактного действия).

Язык

Ключевыми инструкциями, при помощи которых реализуется техника расширения действий, являются оператор ABSTRACT для объявления абстрактного действия и инструкция ACTION+ для добавления к нему реализации.

Примеры

// В данном случае создается ABSTRACT CASE OVERRIDE LAST
exportXls 'Выгрузить в Excel' ABSTRACT CASE (Order);
exportXls (Order o) + WHEN name(currency(o)) == 'USD' THEN {
MESSAGE 'Export USD not implemented';
}

CLASS Task;
run 'Выполнить' ABSTRACT (Task); // ABSTRACT MULTI EXCLUSIVE

CLASS Task1 : Task;
name = DATA STRING[100] (Task);
run (Task1 t) + {
MESSAGE 'Run Task1 ' + name(t);
}


CLASS OrderDetail;
price = DATA NUMERIC[14,2] (OrderDetail);

CLASS InvoiceDetail;
price = DATA NUMERIC[14,2] (InvoiceDetail);
fill ABSTRACT LIST (OrderDetail, InvoiceDetail); // ABSTRACT LIST LAST

fill (OrderDetail od, InvoiceDetail id) + {
price(id) <- price(od);
}
CLASS ABSTRACT Animal;
whoAmI ABSTRACT ( Animal);

CLASS Dog : Animal;
whoAmI (Dog d) + { MESSAGE 'I am a dog!'; }

CLASS Cat : Animal;
whoAmI (Cat c) + { MESSAGE 'I am a сat!'; }

ask () {
FOR Animal a IS Animal DO
whoAmI(a); // для каждого объекта будет выдано соответствующее сообщение
}

onStarted ABSTRACT LIST ( );
onStarted () + {
name(Sku s) <- '1';
}
onStarted () + {
name(Sku s) <- '2';
}
// сначала выполниться 1е действие, потом 2е действие

CLASS Human;
name = DATA STRING[100] (Human);

testName ABSTRACT CASE ( Human);

testName (Human h) + WHEN name(h) == 'John' THEN { MESSAGE 'I am John'; }
testName (Human h) + WHEN name(h) == 'Bob' THEN { MESSAGE 'I am Bob'; }