Объектно-ориентированное программирование

В системе Prolog можно легко реализовать объектно-ориентированный стиль про­граммирования. В данном разделе применение такого стиля демонстрируется на примере простого интерпретатора для объектно-ориентированных программ. При ис­пользовании объектно-ориентированного подхода программа рассматривается как со­стоящая из объектов, которые передают друг другу сообщения. Вычисление происхо­дит в результате формирования объектом ответа на полученное сообщение. Каждый объект имеет собственную область памяти и некоторые процедуры, называемые ме­тодами. Кроме того, объекты могут наследовать методы от других объектов. Приме­няемый при этом механизм аналогичен механизму наследования в методе представ­ления данных на основе фреймов (см. главу 15). Объект отвечает на сообщение, вы­зывая на выполнение один из своих методов, а сообщение определяет, какой метод должен быть выполнен. Действие по передаче сообщения объекту фактически пред­ставляет собой своего рода вызов процедуры. Реализация объектно-ориентированной программы по сути является моделированием процессов передачи сообщений между объектами и формирования объектами ответов на сообщения.

Чтобы ознакомиться с тем, как этот принцип практически осуществляется в сис­теме Prolog, рассмотрим в качестве первого примера объектно-ориентированную про­грамму, касающуюся геометрических фигур. Одним из объектов этой программы яв­ляется прямоугольник, а в состав данного объекта могут входить процедуры для описания прямоугольника и вычисления его площади. Если объекту прямоугольника передается сообщение area ( А) , он отвечает, вычисляя площадь прямоугольника, и переменная А становится конкретизированной значением этой площади. В рассмат­риваемой реализации объект будет представлен как отношение object[ Object, Methods)

где Object — терм, который именует объект (и, возможно, задает его параметры), а Methods — список термов Prolog, определяющих методы. Термы в этом списке име­ют форму предложений Prolog, т.е. обычных фактов и правил Prolog (если не счи­тать того, что они не оканчиваются точкой). Б рассматриваемой реализации Prolog определение любого объекта может задавать целый класс объектов, таких как класс всех прямоугольников, определяемых с помощью предиката rectangle [ Length, Width). В таком случае конкретный прямоугольник со сторонами 4 и 3 определяется



Часть II. Применение языка Prolog в области искусственного интеллекта

с помощью терма rectanglet 4, 3). Это означает, что в общем объект rectang­le { Length, Width] с двумя методами, area и describe, может быть определен следующим образом:

object! rectangle! Length, Width),

[(area(A) :-A is Length * Width),

(describe :-write( 'Rectangle of size ' ) , write( Length * Width)> ]) .

В данной реализации процесс передачи сообщения объекту может быть промоде­лирован с помощью такой процедуры: send( Object, Message)

Для того чтобы объект прямоугольника со сторонами 4 и 3 описал себя и вычис­лил свою площадь, ему достаточно передать соответствующие сообщения:

?- Reel = rectangle; 4, 3} , send! Reel, describe) , send! Reel, area( Area)) . Rectangle of size 4*3 Area = 12

Составить программу для процедуры send{ Object, Message) можно достаточ­но просто. Вначале необходимо обеспечить выборку методов объекта Object. Эти ме­тоды фактически определяют программу Prolog, которая является локальной по от­ношению к Object. Затем нужно вызвать на выполнение эту программу, задав ей в качестве цели сообщение Message. Программа, представленная в виде списка, состо­ит из компонентов в форме Head : - Body или просто Head в случае, если тело явля­ется пустым. Чтобы выполнить программу с целью Message, требуется найти голову предложения, которая согласуется с целью Message, а затем выполнить соответст­вующее тело предложения с помощью собственного интерпретатора Prolog.

Прежде чем реализовать этот замысел в программе, необходимо рассмотреть еще один существенно важный механизм объектно-ориентированного программирова­ния — наследование методов в соответствии с отношением "isa" (является) между объектами. Например, квадрат "isa" прямоугольником. Для вычисления его площа­ди в объекте квадрата может использоваться такая же формула, как и в объектах, прямоугольников. Поэтому для квадрата не требуется его собственный метод area; он может унаследовать этот метод от класса прямоугольников. Для того чтобы полу­чить такую возможность, необходимо определить объект square и дополнительно указать, что он также является прямоугольником.

object! sguare( Side) , [ (describe :-

write! 'Square with, side '),

write( Side)) ]). isa( square( Side), rectangle[ Side, Side)).

Это дает возможность успешно выполнить следующий запрос:

?- send! square( 5), area( Area)!. Дгег - 25

Сообщение area{ Area) обрабатывается таким образом: вначале выполняется поиск метода area ( Area) среди методов объекта square ( 5), но найти его не уда­ется. Затем с помощью отношения isa успешно выполняется поиск этого метода в суперобъекте квадрата - в прямоугольнике rectangle ( 5, 5). Суперобъект имеет соответствующий метод area, который вызывается на выполнение.

Интерпретатор для объектно-ориентированных программ, разработанный в соот­ветствии с замыслом, описанным в данном разделе, приведен в листинге 23.5, а в листинге 23,& приведена законченная объектно-ориентированная программа, отно­сящаяся к геометрическим фигурам.

Глава 23. Метапрограммирование



Листинг 23.5. Простой интерпретатор для объектно-ориентированных программ

'1 Интерпретатор для объектно-оркентированных программ

4 send; Message, Object) если

Т требуется найтиметоды объекта Object и вызвать на выполнение метод,

i который соответствует сообщению Message

send; Object, Message) :-

get_methods( Object, Methods), \ Найти методы объекта Object

process! Message, Methods). % Вызвать на выполнение соответствующий метод

get_methods( Object, Methods! :-

object! Object, Methods!. % Собственные методы

get_methods( Object, Methods) :-
isa( Object, SuperObject) ,
getjmethads! SuperObject, Methods). % Унаследованные методы

process! Message, [Message I _]) . % Использовать факт

process [ Message, [ (Message :- Body) I _] ) :- % Использовать правило call( Body) ,

process! Message, [_ I Methods]} :-process! Message, Methods) .

Наши рекомендации