Студопедия

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

КАТЕГОРИИ:

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






Компоненты-операции






 

Рассмотрение выражения:

 

x + a

 

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

Для реализации этой идеи нужно догадаться, что выражение x + a содержит не один вызов (компонента x), а два. В вычислениях, не использующих объектный подход, + рассматривается как операция сложения двух значений x и a типа REAL. Как уже отмечалось, в чистой ОО-модели единственным механизмом вычислений является вызов компонентов. Следовательно, можно считать, по крайней мере теоретически, что и сложение является вызовом соответствующего компонента.

Для лучшего понимания необходимо обсудить определение типа REAL. Сформулированное ранее объектное правило (лекция 7) подразумевает, что каждый тип основан на каком-то классе. Это в равной мере относится к предопределенным классам, аналогичным REAL, и к классам, определенным разработчиком, таким как POINT. Предположим, что необходимо описать REAL как класс. Нетрудно определить набор существенных компонентов: арифметические операции (сложение, вычитание, изменение знака...), операции сравнения (меньше чем, больше чем...). Итак, первый набросок будет выглядеть так:

 

indexing

description: " Действительные числа (не окончательная версия!)"

class REAL feature

plus (other: REAL): REAL is

-- Сумма текущего значения и other

do

...

end

minus (other: REAL) REAL is

-- Разность между текущим значением и other

do

...

end

negated: REAL is

-- Текущее значение, взятое с противоположным знаком

do

...

end

less_than (other: REAL): BOOLEAN is

-- Текущее значение меньше чем other?

do

...

end

... Другие компоненты...

end

 

При использовании такого описания класса уже нельзя более записывать арифметическое выражение в виде: x + a. Вместо этого надо использовать следующий вызов:

 

x.plus (a)

 

По аналогии, вместо привычного -x следует теперь писать x.negated.

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

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

 

x + a

 

как вызов дополнительного компонента класса REAL. Для реализации такого подхода необходимо переписать компоненту plus таким образом, чтобы для ее вызовов использовать знак операции, а не точечную нотацию. Вот описание класса, реализующее эту цель:

 

indexing

description: " Real numbers"

class REAL feature

infix " +" (other: REAL): REAL is

-- Сумма текущего значения и other

do

...

end

infix " -" (other: REAL) REAL is

-- Разность между текущим значением и other

do

...

end

prefix " -": REAL is

-- Текущее значение, взятое с противоположным знаком

do

...

end

infix " & lt; " (other: REAL): BOOLEAN is

-- Текущее значение меньше чем other?

do

...

end

... Other features...

end

 

Введены два новых ключевых слова - infix и prefix. Единственное синтаксическое новшество заключается в том, что имена компонент не являются идентификаторами (такими как distance или plus), а записываются в одной из двух форм (В следующей лекции будет показано, как определить " развернутый класс". См. " Роль развернутых типов".)

 

infix " §"

prefix " §"

 

где § заменяется конкретным знаком операции (+, -, *, & lt;, & lt; = и др.). Компонент может иметь имя в инфиксной форме только если является функцией с одним аргументом, примерами могут служить plus, minus и less_than в первоначальной версии класса REAL. Префиксная форма может использоваться только для функций без аргументов или атрибутов.

Инфиксные и префиксные компоненты, называемые далее компоненты-операции (operator features), используются аналогично именованным компонентам (identifier features). Существуют лишь два синтаксических различия. Для имен компонентов-операций при их объявлении используются формы infix " §" или prefix " §", а не идентификаторы. Вызов компонентов-операций в случае инфиксных компонент имеет вид:

 

u § v

 

для префиксных:

 

§ u

 

Компоненты-операции поддерживают только квалифицированные вызовы. Неквалифицированный вызов plus (y) в подпрограмме первой версии класса REAL во второй версии должен быть записан в виде Current + y. Для именованных компонентов аналогичная нотация Current.plus (y) допустима, но обычно не используется.

Кроме указанных отличий во всем остальном компоненты-операции полностью синтаксически эквиваленты именованным компонентам, в частности могут наследоваться обычным образом. Не только базовые классы аналогичные REAL, но и любые другие, могут использовать компоненты-операции, например для функции сложения двух векторов в классе VECTOR вполне допустимо использовать инфиксную компоненту " +".

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

 

+ - a / & lt; & gt; = ^ @ # | & amp;

 

Ограничения, налагаемые на первый символ, облегчают распознавание инфиксных и префиксных операций.

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

 

not and or xor and then or else implies

 

Базовые классы (INTEGER и другие) используют так называемые стандартные операции:

[x]. префиксные: + - not

[x]. инфиксные: + - a / & lt; & gt; & lt; = & gt; = = // \ ^ and or xor and then or else implies.

Здесь // обозначает целочисленное деление, \ - остаток при целочисленном делении, ^ - операцию возведения в степень, xor - исключающее " или". В классе BOOLEAN and then и or else являются вариантами and и or (отличия обсуждаются далее), implies обозначает импликацию: выражение a implies b эквивалентно (not a) or else b. Операции, не входящие в число " стандартных", называют свободными операциями. Приведем два примера свободных операций.

[x]. Далее в классе ARRAY будет использован инфиксный компонент-операция " @" для функции, возвращающей указанный элемент массива. Обращение к i -ому элементу массива будет выглядеть как a @ i.

[x]. В класс POINT вместо функции distance можно ввести компонент-операцию " |-| " и расстояние между точками p1 and p2 будет записываться в виде p1 |-| p2, а не как p1.distance(p2).

Все операции имеют фиксированный приоритет, стандартные операции имеют свой обычный приоритет, а все свободные операции обладают более высоким приоритетом.

Использование компонентов-операций позволяет использовать общепринятую нотацию для выражений и одновременно отвечает требованиям полной унификации системы типов. Реализация арифметических и булевых операций как компонентов класса INTEGER вовсе не должна быть причиной снижения производительности. Концептуально a + x является вызовом компонента, но хороший компилятор может создать в результате обработки такого вызова код не менее эффективный, чем компиляторы C, Pascal, Ada или других языков, в которых " +" это жестко зафиксированная языковая конструкция.

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

 

 


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.013 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал