Главная Случайная страница


Полезное:

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


Категории:

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






Статический тип, динамический тип





 

Название последнего свойства предполагает различение "статического типа" и "динамического типа". Тип, который используется при объявлении некоторого элемента, является статическим типом соответствующей ссылки. Если во время выполнения эта ссылка присоединяется к объекту некоторого типа, то этот тип становится динамическим типом этой ссылки.

Таким образом, при объявлении p: POLYGON статический тип ссылки, обозначенной p, есть POLYGON, после выполнения create p динамическим типом этой ссылки также является POLYGON, а после присваивания p:= r, где r имеет тип RECTANGLE и не пусто, динамическим типом становится RECTANGLE.

Правило согласования типов утверждает, что динамический тип всегда должен соответствовать статическому типу.

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

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

В каждый момент во время выполнения у ссылки имеется динамический тип, тип того объекта, к которому она сейчас присоединена (или специальный тип NONE, если эта ссылка пуста). Динамический тип может изменяться в результате операций переприсоединения.

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

 

В развернутом случае нет ссылки, значением x является объект типа T, и T является и статическим типом и единственно возможным динамическим типом для x.

 

Обоснованы ли ограничения?

 

Приведенные выше правила типизации могут иногда показаться слишком строгими. Например, второй оператор в обоих случаях статически отвергается:

 

p:= r; r:= p

 

 

p:= r; x:= p.diagonal

 

В (1) запрещается присваивать многоугольник сущности-прямоугольнику, хотя во время выполнения так получилось, что этот многоугольник является прямоугольником (аналогично тому, как можно отказаться принять собаку из-за того, что на клетке написано "животное"). В (2) компонент diagonal оказался не применим к p несмотря на то, что во время выполнения он, фактически, присутствует.

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

На практике, случаи вида (1) и (2) маловероятны. Присваивания типа p:= r обычно встречаются внутри некоторых управляющих структур, которые зависят от условий, определяемых во время выполнения, например, от ввода данных пользователем. Более реалистичная полиморфная схема может выглядеть так:

 

create r.make (...);...

screen.display_icons -- Вывод значков для разных многоугольников

screen.wait_for_mouse_click -- Ожидание щелчка кнопкой мыши

x:= screen.mouse_position -- Определение места нажатия кнопки

chosen_icon:= screen.icon_where_is (x) -- Определение значка,

-- на котором находится указатель мыши

if chosen_icon = rectangle_icon then

p:= r

elseif...

p:= "Многоугольник другого типа"...

end

... Использование p, например, p.display, p.rotate,...

 

 

В последней строке p может обозначать любой многоугольник, поэтому можно к нему применять только общие компоненты из класса POLYGON. Понятно, что операции, подходящие для прямоугольников, такие как diagonal, должны применяться только к r (например, в первом предложении if). Если придется использовать p в операторах, следующих за оператором if, то к нему могут применяться лишь операции, применимые ко всем видам многоугольников.

В другом типичном случае p просто является формальным параметром процедуры:

 

some_routine (p: POLYGON) is...

 

 

и можно выполнять вызов some_routine (r), корректный в соответствии с правилом согласования типов. Но при написании процедуры об этом вызове еще ничего не известно. На самом деле, вызов some_routine (t) для t типа TRIANGLE или любого другого потомка класса POLYGON будет также корректен, таким образом, можно считать, что p представляет некоторый вид многоугольников - любой из их видов. Тогда вполне разумно, что к p применимы только компоненты класса POLYGON.


Таким образом, в случае, когда невозможно предсказать точный тип присоединяемого объекта, полиморфные сущности (такие как p) весьма полезны.

 

Может ли быть польза от неведения?

 

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

Если вы все еще испытываете неудобство от невозможности написать p.diagonal после присваивания p:=r (в случае (2)), то вы не одиноки. Это шокирует многих людей, когда они впервые сталкиваются с этими понятиями. Мы знаем, что p - это прямоугольник, почему же у нас нет доступа к его диагонали? По той причине, что это было бы бесполезно. После полиморфного присваивания, как показано на следующем фрагменте из предыдущего рисунка, один и тот же объект типа RECTANGLE имеет два имени: имя многоугольника p и прямоугольника r.

 

Рис. 14.7. После полиморфного присваивания

В таком случае, поскольку известно, что объект O2 является прямоугольником и доступен через имя прямоугольника r, зачем пытаться использовать доступ к его диагонали посредством операции p.diagonal? Это не имеет смысла, так как можно просто написать r.diagonal, использовав официальное имя прямоугольника и сняв все сомнения в правомерности применения его операций. Использование имени многоугольника p, которое может с тем же успехом обозначать треугольник, ничего не дает и приводит к неопределенности.

Действительно, полиморфизм теряет информацию: когда в результате присваивания p:=r появляется возможность ссылаться на прямоугольник O2 через имя многоугольника p, то теряется нечто важное - возможность использовать специфические компоненты прямоугольника. В чем тогда польза? В данном случае - ни в чем. Как уже отмечалось, интерес возникает, когда заранее неизвестно, каков будет вид многоугольника p после выполнения команды if some_condition then p:= r else p:= something_else... или когда p является формальным аргументом процедуры и неизвестно, каков будет тип фактического аргумента. Но в этих случаях было бы некорректно и опасно применять к p что-либо кроме компонентов класса POLYGON.

 

Продолжая тему животных, представим, что некто спрашивает: "У вас есть домашний любимец?" и вы отвечаете: "Да, кот!". Это похоже на полиморфное присваивание - один объект известен под двумя именами разных типов: " мой_домашний_любимец " и " мой_кот " обозначают сейчас одно животное. Но они не служат одной цели, первое имя является менее информативным, чем второе. Можно одинаково успешно использовать оба имени при звонке в отдел отсутствующих хозяев компании Любимцы-По-Почте ("Я собираюсь в отпуск, сколько будет стоить наблюдение за моим_домашним_любимцем (или: моим_котом) в течение двух недель?") Но при звонке в другой отдел с вопросом: "Могу ли я привезти во вторник моего домашнего любимца, чтобы отстричь когти?", вы не запишетесь на прием, пока не уточните, что имели в виду своего кота.

 







Date: 2015-12-13; view: 445; Нарушение авторских прав



mydocx.ru - 2015-2024 year. (0.007 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию