Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pol_Grem_-_ANSI_Common_Lisp_High_tech_-_2012.pdf
Скачиваний:
28
Добавлен:
12.03.2016
Размер:
4.85 Mб
Скачать

11.10. Две модели

199

капсу­ля­ци­ей­ в малом­ масшта­бе­ (стр. 120). Функции­ stamp и reset ис­ пользуют общую­ пере­мен­ную­ counter, одна­ко­ вызы­­вающий­ код ниче­го­ о ней не знает­ и не может­ изме­нить­ ее напря­мую­.

В Common Lisp основ­ным­ мето­дом­ разде­ле­ния­ инфор­ма­ции­ на публич­­ ную и приват­ную­ явля­ют­ся­ паке­ты­. Чтобы­ огра­ни­чить­ доступ­ к чему­- либо,­ мы кладем­ это в пакет,­ экспор­ти­руя­ из него­ лишь имена,­ являю­­ щиеся­ частью­ внешне­го­ интер­фей­са­.

Для инкап­су­ля­ции­ слота­ доста­точ­но­ экспор­ти­ро­вать­ лишь функции­ досту­па­ к нему,­ но не имя само­го­ слота­. Напри­мер,­ мы можем­ опре­де­­ лить класс counter и связать­ с ним мето­ды­ increment и clear:

(defpackage "CTR"

(:use "COMMON-LISP")

(:export "COUNTER" "INCREMENT" "CLEAR"))

(in-package ctr)

(defclass counter () ((state :initform 0)))

(defmethod increment ((c counter)) (incf (slot-value c ’state)))

(defmethod clear ((c counter)) (setf (slot-value c ’state) 0))

Функции­ вне паке­та­ ctr будут­ иметь возмож­ность­ созда­вать­ экзем­п­ля­­ ры counter и вызы­­вать increment и clear, одна­ко­ не будут­ иметь досту­па­ к само­му­ слоту­ и имени­ state.

А если­ вы хоти­те­ не просто­ разде­лить­ внешний­ и внутрен­ний­ интер­­ фейсы­ класса,­ но и сделать­ невоз­мож­ным­ сам доступ­ к значе­нию­ слота,­ то може­те­ посту­пить­ так: просто­ отинтер­ни­руй­те­ (unintern) имя слота­ после­ выпол­не­ния­ кода,­ кото­рый­ ссыла­ет­ся­ на него:­

(unintern ’state)

Теперь­ сослать­ся­ на слот невоз­мож­но­ ни из како­го­ паке­та­.°

11.10. Две модели

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

В моде­ли­ пере­да­чи­ сооб­ще­ний­ мето­ды­ принад­ле­жат­ объек­там­ и насле­­ дуют­ся­ так же, как слоты­. Чтобы­ найти­ площадь­ объек­та,­ нужно­ по­ слать ему сооб­ще­ние­ area:

tell obj area

200

Глава 11. CLOS

Это сооб­ще­ние­ вызы­­вает­ соот­вет­ст­вую­щий­ метод,­ кото­рый­ obj опре­де­­ ляет­ или насле­ду­ет­.

Иногда­ нам прихо­дит­ся­ сооб­щать­ допол­ни­тель­ные­ аргу­мен­ты­. Напри­­ мер, метод­ move может­ прини­мать­ аргу­мент,­ опре­де­ляю­щий­ дальность­ пере­ме­ще­ния­. Чтобы­ пере­мес­тить­ obj на 10, пошлем­ ему следую­щее­ со­ обще­ние:­

tell obj move 10

Если­ запи­сать­ это другим­ спосо­бом:­

(move obj 10)

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

В моде­ли­ пере­да­чи­ сооб­ще­ний­ мето­ды­ принад­ле­жат­ объек­там,­ в то время­ как в моде­ли­ обобщен­ных­ функций­ мето­ды­ специа­ли­зи­ру­ют­ся­ для объек­тов­. Если­ мы будем­ специа­ли­зи­ро­вать­ся­ только­ для перво­го­ аргу­мен­та,­ то эти две моде­ли­ будут­ по сути­ одним­ и тем же. Но в моде­ли­ обобщен­ных­ функций­ мы можем­ пойти­ дальше­ и специа­ли­зи­ро­вать­ся­ для любо­го­ необ­хо­ди­мо­го­ коли­че­ст­ва­ аргу­мен­тов­. Таким­ обра­зом,­ пере­­ дача­ сооб­ще­ний ­– лишь част­ный­ случай­ обобщен­ных­ функций,­ с помо­­ щью кото­рых­ мож­но симу­ли­ро­вать­ пере­да­чу­ сооб­ще­ний,­ специа­ли­зи­­ руя мето­ды­ только­ по перво­му­ аргу­мен­ту­.

Итоги главы

1.В объект­но­-ориен­ти­ро­ван­ном­ програм­ми­ро­ва­нии­ функция­ f опре­де­­ ляет­ся­ неяв­но­ при опре­де­ле­нии­ мето­дов­ f для разных­ объек­тов­. Объ­ екты­ насле­ду­ют­ мето­ды­ от своих­ роди­те­лей­.

2.Опре­де­ле­ние­ класса­ напо­ми­на­ет­ более­ много­слов­ное­ опре­де­ле­ние­ структу­ры­. Разде­ляе­мый­ слот принад­ле­жит­ всему­ классу­.

3.Класс насле­ду­ет­ слоты­ своих­ супер­клас­сов­.

4.Предки­ класса­ упоря­до­че­ны­ в соот­вет­ст­вии­ со списком­ предше­ст­во­­ вания­. Алго­ритм­ предше­ст­во­ва­ния­ легче­ всего­ понять­ визу­аль­но­.

5.Обобщен­ная­ функция­ состо­ит­ из всех мето­дов­ с тем же именем­. Ме­ тод опре­де­ля­ет­ся­ именем­ и специа­ли­за­ци­ей­ своих­ пара­мет­ров­. Ме­ тод, исполь­зуе­мый­ при вызо­ве­ обобщен­ной­ функции,­ опре­де­ля­ет­ся­ соглас­но­ поряд­ку­ предше­ст­во­ва­ния­.

6.Первич­ные­ мето­ды­ могут­ быть допол­не­ны­ вспомо­га­тель­ны­ми­. Стан­ дартная­ комби­на­ция­ мето­дов­ озна­ча­ет­ исполь­зо­ва­ние­ around-мето­­ дов, если­ тако­вые­ имеют­ся;­ в против­ном­ случае­ вызы­­вают­ся­ снача­­ ла before-, потом­ первич­ный,­ затем­ after-мето­ды­.

7.В опера­тор­ной­ комби­на­ции­ мето­дов­ все первич­ные­ мето­ды­ рассмат­­ рива­ют­ся­ как аргу­мен­ты­ задан­но­го­ опера­то­ра­.

Упражнения

201

8.Инкап­су­ля­ция­ может­ быть осуще­ст­в­ле­на­ с помо­щью­ паке­тов­.

9.Суще­ст­ву­ют­ две моде­ли­ объект­но­-ориен­ти­ро­ван­но­го­ програм­ми­ро­­ вания­. Модель­ обобщен­ных­ функций­ явля­ет­ся­ обобще­ни­ем­ моде­ли­ пере­да­чи­ сооб­ще­ний­.

Упражнения

1.Опре­де­ли­те­ пара­мет­ры­ accessor, initform, initarg для классов,­ опре­­ делен­­ных на рис. 11.2. Внеси­те­ необ­хо­ди­мые­ правки,­ чтобы­ код бо­ лее не исполь­зо­вал­ slot-value.

2.Пере­пи­ши­те­ код на рис. 9.5 так, чтобы­ сферы­ и точки­ были­ класса­­ ми, а introspect и normal – обобщен­ны­ми­ функция­ми­.

3.Имеет­ся­ набор­ классов:­

(defclass a (c d) ...

)

(defclass e () ...

)

(defclass b (d c) ...

)

(defclass f (h) ...

)

(defclass

c

()

...)

 

(defclass g (h) ...

)

(defclass

d

(e

f g) ...

)

(defclass h () ...

)

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

(b)Повто­ри­те­ анало­гич­ную­ проце­ду­ру­ для b.

4.Имеют­ся­ следую­щие­ функции:­

precedence: прини­ма­ет­ объект­ и возвра­ща­ет­ для него­ список­ пред­ шест­во­ва­ния­ классов­ по убыва­нию­ специ­фич­но­сти­.

methods: прини­ма­ет­ обобщен­ную­ функцию­ и возвра­ща­ет­ список­ всех ее мето­дов­.

specializations: прини­ма­ет­ метод­ и возвра­ща­ет­ список­ специа­ли­­ заций­ его пара­мет­ров­. Каждый­ элемент­ возвра­щае­мо­го­ списка­ будет­ либо­ классом,­ либо­ списком­ вида­ (eql x), либо­ t (для неспе­­ циали­зи­ро­ван­но­го­ пара­мет­ра)­ .

С помо­щью­ пере­чис­лен­­ных функций­ (не пользу­ясь­ compute-appli­cab­­ le-methods или find-method) опре­де­ли­те­ функцию­ most-spec-app-meth, прини­маю­щую­ обобщен­ную­ функцию­ и список­ аргу­мен­тов,­ с кото­­ ры­ми она будет­ вызва­на,­ и возвра­щаю­щую­ наибо­лее­ специ­фич­ный­ приме­ни­мый­ метод,­ если­ тако­вые­ имеют­ся­.

5.Изме­ни­те­ код на рис. 11.2 так, чтобы­ при каждом­ вызо­ве­ обобщен­­ ной функции­ area увели­чи­вал­ся­ некий­ глобаль­ный­ счетчик­. Функ­ ция не долж­на менять­ свое пове­де­ние­ ника­ким­ иным обра­зом­.

6.Приве­ди­те­ пример­ зада­чи,­ трудно­раз­ре­ши­мой­ в том случае,­ когда­ лишь первый­ аргу­мент­ обобщен­ной­ функции­ может­ быть специа­ли­­ зиро­ван­.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]