Студопедия — Теоретические сведения. 1. Создать класс «компьютер» со свойствами: Модель, процессор, количество оперативной памяти, объем жесткого диска
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Теоретические сведения. 1. Создать класс «компьютер» со свойствами: Модель, процессор, количество оперативной памяти, объем жесткого диска

1. Создать класс «компьютер» со свойствами: Модель, процессор, количество оперативной памяти, объем жесткого диска, видеокарта. Затем создать экземпляр класса «компьютер» с какими-либо характеристиками.

// create-accessor read-write – фацет, оговаривающий возможности работы со слотами

(defclass PC;определяем класс PC

(is-a USER)

(role concrete)

(pattern-match reactive)

(slot model (type SYMBOL) (create-accessor read-write))

(slot CPU (type SYMBOL) (create-accessor read-write))

(slot RAM (type INTEGER) (create-accessor read-write))

(slot HDD (type INTEGER) (create-accessor read-write))

(slot videocard (type SYMBOL) (create-accessor read-write)))

 

//инстанцируем объект

 

(definstances PC (asus of PC (model 1201n) (CPU atom) (RAM 2) (HDD 250) (videocard ion)))

 

//сделать бы какое-нибудь правило поведения для класса, но лень

 

Теоретические сведения

Использование объектно-ориентированных средств в CLIPS позволяет значительно упростить программирование правил, поскольку для обновления данных можно применять механизм передачи и обработки сообщений методами классов.

Объекты в CLIPS могут быть описаны как символьные, строковые, целые или вещественные числа, значения с множеством полей, внешние адреса или объекты определенного пользователем класса. При описании объектов выделяют 2 основные части: свойства и их поведение. Класс — это шаблон общих свойств и поведения объектов данного класса.

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

К объектам простых типов обращаются, подставляя их значения, и они создаются и удаляются исключительно окружением CLIPS по мере необходимости. Объекты простых типов не имеют имен и слотов-заполнителей, и их классы предопределены CLIPS. Поведение объектов простых типов такое же, как и у объектов пользовательских классов. Пользователь может создавать собственные обработчики сообщений (которыми и оперируют классы в CLIPS — обычно над слотами объекта выполняются какие–то действия при получении объектом тех или иных сообщений) и присоединить их к объектам простых типов. Тем не менее, предполагается, что простые типы не будут часто использоваться в контексте объектно–ориентированного программирования в CLIPS.

 

Ниже представлены несколько примеров объектов и их классов:

Объект (печатное представление) Класс
Rolls–Royce SYMBOL
"Rolls–Royce" STRING
8.0 FLOAT
  INTEGER
(8.0 Rolls-Royce 8 [Rolls-Royce]) MULTIFIELD
<Pointer- 00CF61AB> EXTERNAL-ADDRESS
[Rolls-Royce] CAR (пользовательский класс)

 

На объект пользовательского класса ссылаются по имени или адресу, и они создаются и удаляются явно через сообщения и специальные функции. Свойства объекта пользовательского класса определяются набором слотов, которые объект получает от его класса. Как ранее упоминалось, слоты — это поименованные одиночные поля или мультиполя (multifields). Например, объект Rolls–Royce — это объект класса CAR. Одним из слотов в классе CAR может быть "цена" (price), и значение этого слота для объекта Rolls–Royce составило бы, например, $75 000. Поведение объекта указано в терминах процедурного кода называемого обработчики сообщений (message-handlers), которые присоединены к классу объекта. Все объекты пользовательского класса имеют одинаковый набор слотов, но каждый объект может иметь различные значения для этих слотов. Однако два объекта, которые имеют одинаковый набор слотов, не обязательно принадлежат к одному и тому же классу, так как два различных класса могут иметь идентичные наборы слотов.

Базовая разница между слотами объекта и шаблона (неупорядоченного факта) состоит в наследовании. Наследование позволяет описывать свойства и поведение класса описывать в терминах других классов. COOL (CLIPS Object–Oriented Language — Объектно–ориентированный язык CLIPS) поддерживает множественное наследование: класс может напрямую наследовать слоты и обработчики сообщений от более чем одного класса. Так как наследование полезно только для слотов и обработчиков сообщений, часто не значимо наследование от одного из классов простых типов, как, например, MULTIFIELD или NUMBER. Это связано с тем, что эти классы не могут иметь слотов и обычно не имеют обработчиков сообщений.

Пользовательские классы могут быть конкретными и абстрактными. Абстрактные классы играют ту же роль, что и виртуальные классы в С++, то есть они используются только для порождения производных классов. Например, если имеем абстрактный класс PERSON, то используя механизм наследования можно создать производные классы WOMAN и MAN.

Пример.

Первым делом определим класс pistol, в котором будут перечислены свойства, необходимые для моделирования.

(defclass pistol

(is-a USER)

(role concrete)

(pattern-match reactive)

(slot safety (type SYMBOL) (create-accessor read-write))

(slot slide (type SYMBOL) (create-accessor read-write))

(slot hammer (type SYMBOL) (create-accessor read-write))

(slot chamber (type INTEGER) (create-accessor read-write))

(slot magazine (type SYMBOL) (create-accessor read-write))

(slot rounds (type INTEGER) (create-accessor read-write)))

Первые три слота — системные. Они нужны объектно-ориентированной надстройке CLIPS (COOL — CLIPS object-oriented language). Эти слоты COOL извещают о том, что

pistol — это пользовательский класс;

pistol является конкретным классом, т.е. возможно создание экземпляров этого класса (альтернативный тип — абстрактный класс, который играет ту же роль, что и виртуальный класс в C++);

экземпляры класса pistol могут быть использованы в качестве объектов данных, которые можно сопоставлять с условиями в правилах и использовать в действиях, определенных правилами.

Следующие пять слотов представляют свойства и члены данных класса:

слот safety (предохранитель) может содержать символ on или off;

слот slide (затвор) может содержать значение forward или back, т.е. хранит информацию о положении затвора;

слот hammer (курок) содержит информацию о состоянии курка, back или down;

слот chamber (патронник) содержит значение 1 или 0, в зависимости от того, есть ли патрон в патроннике;

слот magazine (обойма) может содержать значение in или out, в зависимости от того, вставлена ли обойма;

слот rounds (патроны) содержит текущее количество патронов в обойме.

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

(definstances pistols (РРК of pistol (safety on)

(slide forward) (hammer down) (chamber 0) (magazine out) (rounds 6)

Этот экземпляр, РРК, правильно уложен — обойма вынута из рукоятки, пистолет установлен на предохранитель, затвор в переднем положении, курок опущен, а патронник пуст. В обойме имеется 6 патронов.

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

есть ли патрон в патроннике;

произведен ли выстрел.

Для этого можно использовать следующий шаблон:

(deftemplate range-test

(field check (type SYMBOL) (default no))

(field fired (type SYMBOL) (default no)))

Первое правило будет устанавливать в рабочую память программы задачу range-test.

(defrule start

(initial-fact) =>

(assert (range-test)))

При активизации этого правила в рабочую память будет добавлено

(range-test (check no) (fired no))

Следующие три правила будут проверять правильно ли снаряжен

пистолет.

(defrule check

(object (name [PPK]) (safety on) (magazine out))

?T <- (range-test (check no))

=>

(send [PPK] clear)

(modify?T (check yes))

)

Правило check заключается в том, что если пистолет стоит на предохранителе (safety on), обойма вынута (magazine out) и пистолет не был проверен, то нужно очистить патронник и проверить, нет ли в нем патрона. Обработчик сообщений clear для класса pistol будет выглядеть следующим образом:

(defmassage-handler pistol clear ()

(dynamic-put chamber 0)

(ppinstance)

)

В первой строке объявляется, что clear является обрабртчиком

сообщения для класса pistol, причем этот обработчик не требует передачи аргументов. Оператор во второй строке «очищает» патронник. Присвоение выполняется независимо от того, какое текущее значение имеет слот chamber - 0 или 1. Оператор в третьей строке требует, чтобы экземпляр распечатал информацию о текущем состоянии своих слотов.

В следующих двух правилах обрабатываются ситуации, когда пистолет снаряжен неправильно, - не установлен на предохранитель или в него вставлена обойма. Правило correct1 устанавливает пистолет на предохранитель, а правило correct2 извлекает из него обойму.

(defrule correct1

(object (name [PPK]) (safety off))

(range-test (check no))

=>

(send [PPK] safety on)

)

(defrule correct2

(object (name [PPK]) (safety on) (magazine in))

(range-test (check no))

=>

(send [PPK] drop)

)

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

(defmessage-handler pistol safety (?on-off)

(dynamic-put safety?on-off)

(if (eq?on-off on)

then (dynamic-put hammer down)

)

)

Обработчик сообщения safety принимает единственный аргумент, который может иметь только два символических значения on или off. В противном случае нам пришлось бы разработать два обработчика: один для сообщения safety-on, а другой – для сообщения safety-off. Учтите, что в некоторых моделях, например в Walther PPK, при установке пистолета на предохранитель патронник очищается автоматически.

Обработчик сообщения drop просто извлекает обойму из пистолета.

(defmessage-handler pistol drop ()

(dynamic-put magazine out)

)

Теперь, когда обеспечено правильное исходное снаряжение пистолета, можно приступить к стрельбе. Следующее правило обеспечивает вставку обоймы в пистолет перед стрельбой:

(defrule mag-in

(object (name [PPK]) (safety on) (magazine out))

(range-test (fired no) (check yes))

=>

(send [PPK] seat)

)

Обработчик сообщения seat выполняет действия, противоположные тем, которые выполняет обработчик drop.

(defmessage-handler pistol seat ()

(dynamic-put magazine in)

)

Можно было бы, конечно, включить в программу и следующее правило mag-in:

(defrule mag-in

?gun <- (object (name [PPK]) (safety on) (magazine out))

(range-test (fired no) (check yes))

=>

(modify?gun (magazine in)

)

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

(defrule load

(object (name [PPK]) (magazine in) (chamber 0))

=>

(send [PPK] rack)

)

На примере обработчика сообщения rack вы можете убедиться в

справедливости нашего замечания о том, что обработку данных внутри объекта нужно поручать методам этого объекта, а не включать прямо в правило.

(defmessage-handler pistol rack ()

(if (> (dynamic-get rounds) 0)

then (dynamic-put chamber 1)

(dynamic-put rounds (- (dynamic-get rounds) 1))

(dynamic-put slide forward)

else (dynamic-put chamber 0)

(dynamic-put slide back)

)

)

В этом обработчике обеспечивается досылка патрона в патронник в том случае, если в обойме имеются патроны. Следующее правило подготавливает пистолет к стрельбе, снимая его с предохранителя. Обратите внимание на то, что в нем повторно используется сообщение safety, но на этот раз с аргументом off.

(defrule ready

(object (name [PPK]) (chamber 1))

=>

(send [PPK] safety off)

)

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

(defrule fire

(object (name [PPK]) (safety off))

?T <- (range-test (fired no))

=>

(if (eq (send [PPK] fire) TRUE)

then (modify?T (fired yes)))

)

Обратите внимание, что в данном правиле используется обработчик сообщения, которое возвращает значение. Анализируя его, можно выяснить, произведен ли выстрел, т.е. выполнена ли в действительности та операция, которая «закреплена» за этим сообщением. Если в патроннике был патрон и пистолет был снят с предохранителя, то обработчик сообщения вернет значение TRUE (после того, как выведет на экран BANG!). В противном случае он вернет FALSE (после того, как выведет на экран click).

(defmessage-handler pistol fire ()

(if (and

(eq (dynamic-get chamber) 1)

(eq (dynamic-get safety) off)

)

then (printout t crlf “BANG!” t crlf)

TRUE

else (printout t crlf “click” t crlf)

FALSE

)

)

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

После завершения стрельбы пистолет нужно вновь вернуть в положение «по-походному». Начинается это с того, что пистолет устанавливается на предохранитель, для чего используется ранее разработанный обработчик сообщения safety.

(defrule unready

(object (name [PPK]) (safety off))

(range-test (fired yes))

=>

(send [PPK] safety on)

)

Следующая операция – вынуть обойму. Обратите внимание, что в нем мы вновь обращаемся к обработчику сообщения drop.

(defrule drop

(object (name [PPK]) (safety on))

(range-test (fired yes))

=>

(send [PPK] drop)

)

Последнее правило выбрасывает патрон из патронника, вызывая обработчик сообщения clear.

(defrule unload

(object (name [PPK]) (safety on) (magazine out))

(range-test (fired yes))

=>

(send [PPK] clear)

)

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

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




<== предыдущая лекция | следующая лекция ==>
Теоретические сведения. 1) Внести в базу фактов, факты first, second, third | Упражнение 1

Дата добавления: 2015-08-31; просмотров: 1004. Нарушение авторских прав; Мы поможем в написании вашей работы!



Шрифт зодчего Шрифт зодчего состоит из прописных (заглавных), строчных букв и цифр...

Картограммы и картодиаграммы Картограммы и картодиаграммы применяются для изображения географической характеристики изучаемых явлений...

Практические расчеты на срез и смятие При изучении темы обратите внимание на основные расчетные предпосылки и условности расчета...

Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Билиодигестивные анастомозы Показания для наложения билиодигестивных анастомозов: 1. нарушения проходимости терминального отдела холедоха при доброкачественной патологии (стенозы и стриктуры холедоха) 2. опухоли большого дуоденального сосочка...

Сосудистый шов (ручной Карреля, механический шов). Операции при ранениях крупных сосудов 1912 г., Каррель – впервые предложил методику сосудистого шва. Сосудистый шов применяется для восстановления магистрального кровотока при лечении...

Трамадол (Маброн, Плазадол, Трамал, Трамалин) Групповая принадлежность · Наркотический анальгетик со смешанным механизмом действия, агонист опиоидных рецепторов...

ЛЕКАРСТВЕННЫЕ ФОРМЫ ДЛЯ ИНЪЕКЦИЙ К лекарственным формам для инъекций относятся водные, спиртовые и масляные растворы, суспензии, эмульсии, ново­галеновые препараты, жидкие органопрепараты и жидкие экс­тракты, а также порошки и таблетки для имплантации...

Тема 5. Организационная структура управления гостиницей 1. Виды организационно – управленческих структур. 2. Организационно – управленческая структура современного ТГК...

Методы прогнозирования национальной экономики, их особенности, классификация В настоящее время по оценке специалистов насчитывается свыше 150 различных методов прогнозирования, но на практике, в качестве основных используется около 20 методов...

Studopedia.info - Студопедия - 2014-2024 год . (0.014 сек.) русская версия | украинская версия