Диспетчеризация сообщений

При посылке сообщения объекту с помощью функции send CLIPS просматривает список предшествования класса для класса активного объекта и определяет набор обработчиков сообщений, которые применимы к данному сообщению. CLIPS использует роли (around, before, primary и after), заданные при определении этих обработчиков, для определения порядка, в котором данные сообщения должны быть выполнены, и после этого выполняет все обработчики в установленном порядке. Обработчик, связанный с классом, называется более определенным, чем обработчик того же сообщения, связанный с суперклассом. Весь этот процесс в целом называется диспетчеризацией сообщений.

Процесс диспетчеризации сообщений немного напоминает процесс родового связывания, описанный в предыдущей главе. Однако он имеет и некоторые существенные отличия, которые будут рассмотрены в данном разделе.

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

Множество всех применимых обработчиков сообщений сортируется по четырем группам, соответствующим ролям, и эти четыре группы дополнительно сортируются по определенности класса. Обработчики around, before и primary упорядочиваются от более определенного класса к более общему, тогда как обработчики after упорядочиваются от более общего к более определенному. Принцип выполнения последовательности обработчиков следующий:

Ø обработчики around начинают выполнение от более определенного к более общему (каждый обработчик around должен явно позволять выполне­ние других обработчиков);

Ø обработчики before выполняются последовательно от более опреде­ленного к более общему;

Ø обработчики primary начинают выполнение от более определенного к более общему (более определенные обработчики primary должны явно позволять выполнение более общих обработчиков);

Ø обработчики primary заканчивают выполнение от более общих к более определенным;

Ø обработчики after выполняются (друг за другом) от более общего к более определенному;

Ø обработчики around завершают выполнение от более общего к более определенному.

Должен существовать, по крайней мере, один применимый обработчик primary для сообщения. Иначе будет сгенерировано сообщение об ошибке.

Если один обработчик в процессе выполнения вызывает другой обработчик, то второй обработчик называется скрытым первым. Обработчик around скрывает все обработчики за исключением более определенных обработчиков around. Обработчик primary скрывает все более общие обработчики primary.

Обработка сообщения должна быть реализована с использованием деклара­тивной технологии, насколько это возможно. Только роли обработчиков должны определять, какие обработчики получат выполнение. Для этого по возможности используйте только обработчики before и after и наиболее определенные обработчики primary. Это позволяет каждому обработчику сообщения быть полностью независимым от других обработчиков сообще­ний. Однако если необходимо использование обработчиков around или скрытых обработчиков primary, то такие обработчики должны брать на себя выполнение части процесса диспетчеризации сообщений, вызывая скрытые обработчики. Как уже упоминалось, такой подход называется императивным. Для выполнения скрытых обработчиков служат функции call-next-handler и override-next-handier. С их помощью обработчик может вызвать некоторый скрытый обработчик один или несколько раз.

Для иллюстрации последовательности вызовов скрытых обработчиков рассмотрим последовательность обработчиков сообщений.