Листинг 23.6. Объектно-ориентированная программа, относящаяся к геометрическим фигурам

/* polygon! [Sidel, Side2, ...])

/ \

/ \

rectsngiet Length, Width) reg oolygocl Side, N)
\ / \

\ / \

souaref Side) pentagon! Sidei */

object! polygon! sides) , [ ( perimeter) P) :-

gum(Sides, P> ) ] ) .

object; reg_polygon[ Side, Ы) , [ ( perimeter! F) :.-E is Side * N) , ( describe :- write! 'Regular polygon') ) ] ).

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

write! 'Sguare with side ' ) , write [ Side) ) 3 ) •

object; rectangle! Length, Width) , [ ( area{ A) :-

A is Length * Width) , ( describe :-

write! 'Rectangleof size ' ) , write! Length * Width) ) ] ).

object! pentagon! Side) ,

[ ( describe :- write! 'Pentagon') ) ] ).

isa( sguare! Side) , rectangle! Side, Side)) .

isa( sguare! Side! , reg_polygon [ .Side, 4) ) .



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


isal rectangle! Length, Widllh) , polygon! 5LengthrWidthFLength,Width])) .

j.sat pentagon [ Side), reg_polygon [ Side, 5)).

isal reg_polygon( Side, M), polygon)L!) :-

raafcelist[ Side, N, L) .

% makelistl item, И, List; если

i List - это список, в котором элемент Item появляется Краз

makelistl_, 0, []) .

makelist(Item, N, [Item ! List]) :-N > 0, N1 is N - 1, makeiistl item, HI, List).

& suml ListOfNumbers , Sum)если 'i Sum - это сумма чисел в списке ListofNumbers

sura ( [ ] , 0) ,

5шп( [Number | Numbers] , Sum) :-sum[ Numbers, SumlJ, Sum is Suml + Number,

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

В качестве дополнительной иллюстрации стиля объектно-ориентированного про­граммирования, который поддерживается интерпретатором, приведенным в листинге 23.5, рассмотрим ситуацию, показанную на рис. 23.1. На этом рисунке изображен мир робота: определенное количество блоков, расставленных на столе в виде столби­ков. На потолке установлена телекамера, которая снимает вид сверху объектов, на­ходящихся на столе. Для простоты предположим, что все блоки представляют собой кубики со сторонами, равными 1. Блоки имеют имена а, Ь, .... а камера позволяет распознавать по именам те блоки, которые не закрыты сверху, и определять их ко­ординаты по отношению к осям к и у. Предположим, что перед нами стоит задача определения местонахождения объектов, т.е. их координат х, у и z. С каждым бло­ком связана некоторая локальная информация, поэтому известно, какой блок (если он существует) находится непосредственно над ним или под ним. Поэтому координа­ты х - у произвольного блока В могут быть получены одним из двух способов, опи­санных ниже.

1, Если блок не закрыт сверху другим блоком, то он может быть обнаружен с
помощью камеры, которая определит координаты х. - у этого блока. Такая
задача решается путем передачи камере сообщения look ( В, X, Y).

2. Если блок В расположен под некоторым блоком В1, то он находится вместе с
ним в одном и том же столбике, а все блоки одного столбика имеют одинако­
вые координаты х - у. Поэтому, чтобы определить координаты х - у блока
В, необходимо отправить сообщение xy_coord( X, Y) блоку В1.

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


I Телекамера


4-

ь


х Рис. 23.1. Мир робота

Аналогичные рассуждения позволяют найти способ определения координаты z любого блока. Если некоторый блок В стоит на столе, то его координата z равна 0, в. если В стоит на другом блоке В1, то достаточно передать сообщение z_coord( Z1) блоку Б1 и сложить полученную высоту Z1 с высотой В1, определив тем самым зна­чение координаты 2 блока В. Такие операции выполняются в программе, приведен­ной в листинге 23.7, где блоки а, Ы т.д. определены как экземпляры класса блоков block ( BlockName), от которого они наследуют методы xycoord и z_coo!:d.