Rationale for Ada 2005: Object oriented model
RUSTOPBACKNEXT
ENG |
3. The prefixed notation
@ As mentioned in the Introduction, the Ada 95 object oriented model has been criticized for not being really OO since the notation for applying a subprogram (method) to an object emphasizes the subprogram and not the object. Thus given
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale for Ada 2005: Object oriented model
@ENGRUSTOPBACKNEXT3. Префиксная нотация
@ Как было упомянуто во Введении, объектно-ориентированная модель ada критиковалась за то, что она не совсем соответсвовала концепции OOП, так как в ней при применении подпрограммы (метода) к объекту делался упор на подпрограмму, а не на объект. Рассмотрим пакет:
|
@ обычный вызов фунции будет выглядеть так:
|
@ в то время как ООП требует следующий порядок применения операции Op к объекту Y типа T:
|
@ В некоторых языках жестко ориентированных на ООП, например, таком как Smalltalk, имеют дело исключительно только с объектами и любые действия связаны только с ними. Таким образом, сложение двух чисел 2 и 3 могут рассматриваться как посылка сообщения добавить объекту 2 'прибавиться' к объекту 3. Понятно, что это весьма циничный и экстремиский подход.
@ Старые языки были основаны на представлении, что подпрограммы являются доминирующими, и что они действуют на параметры, которые могут быть числами такими как 2 или обозначать объекты, такие как круг. Ада 95 получает представление, которое отражает её Паскальные корни более чем 20 летней давности. Таким образом, если Area - функция возвращающаят площадь круга, тогда мы имеем право написать:
|
@ Однако, при рассмотрении задач и защищенных объектов Ada получает представление OOП в котором на первом месте объект. Таким образом, имея задачу Actor с точкой входа Start мы вызываем вход Start следующим образом:
|
@ Ада 95 уже имеет объектную нотацию, хотя это относится только к параллельным объектам, таким как задачи. Другие объекты и, в частности, объекты теговых типов должны были использовать традиционную подпрограммную нотацию.
@ Главное неудобство подпрограммной нотации состоит в том, что при необходимости вызвать фунцию содержащуюся в неком пакете необходимо указывать сам пакет:
|
@ Есть две ситуации, когда пакет P может не упоминаться: во-первых - когда вызов процедуры находится непосредственно в пакете P, во-вторых - когда у нас определен спецификатор использования (use) для пакета P (и даже в этом случае это не всегда дает необходимую видимость). Но это особые случаи.
@ В Аде 2005 мы можем заменить вызов P.Op (Y...), так называемой, префиксной нотацией:
|
@ при условии, что
@ Причина того, что нам нет необходимости упоминать пакет состоит в том, что мы имея объект можем идентифицировать его тип и, следовательно, все примитивные операции этого типа. Заметим, что надклассовую операцию можно вызвать таким образом только если она объявлена в том же самом месте где и примитивные операции T (или один из его предков).
@ Есть много преимуществ префиксной нотации, и как мы можем видеть, самой важной из них является лёгкость обслуживания и отсутствие необходимости упоминать пакет, содержащий объявление операции. Необходимость упоминать пакет часто является обременительным, потому что в сложных ситуациях вовлекающих несколько уровней наследования не всегда очевидно где операция объявлена. Особенно когда операции объявлены неявно и когда операции всего класса вовлечены. Тем более, если мы изменяем структуру по тем или иным причинам, тогда операции могли бы меняться.
@ В качестве примера рассмотрим иерархию геометрических объектов на плоскости. Всем объектам дадим координаты x и y (это - позиция центра тяжести объекта). Зададим атрибуты специфические для каждого типа объектов (например, радиус для круга). Кроме того, у объектов могут быть и общие свойства, такие как площадь, расстояния от начала координат и момент инерции.
@ Есть много способов структурировать такую иерархию. У нас мог бы быть пакет, объявленный как корневой абстрактный тип, и пакет с несколькими производными типами.
|
@ Этот пакет определяет корневой тип с двумя абстрактными операциями Area и MI (момент инерции) и конкретную операцию Distance. Тогда мы можем написать:
|
@ (В дальнейшем обсуждении мы предположим, что спецификаторы использования (use) не определены. Это весьма реалистичо, потому что во многих проектах запрещают спецификаторы использования). Объявив некоторые объекты, такие как A_Circle и A_Triangle мы можем применить операции Area, Distance, и MI. На Аде 95 мы должны были написать:
|
@ Заметим, что операция Distance унаследована и неявно объявлена в пакете Shapes для всех типов даже при том, что нет никакого упоминания о ней в тексте пакета Shapes. Однако, если бы мы использовали Аду 2005 и префиксную нотацию, тогда мы могли бы написать:
|
@ где нет никакого упоминания о пакете Shapes вообще.
@ Заметим, что метод Distance - один и тот же для всех типов, и было бы более безопасно избежать риска его изменения, сделав его надкласового типа. Таким образом, мы изменяем объявление Distance в пакете Root следующим образом:
|
@ и перекомпилируем нашу программу. Но на Аде 95 мы потерпим неудачу. Почему? Потому что надклассовые операции не наследуются. Таким образом, есть только одна функция Distance, и она объявлена в пакете Shape. Таким образом, все наши вызовы Distance должны быть изменены на:
|
@ Однако, если бы мы использовали префиксную нотацию тогда нам ничего не надо было менять.
@ Наш босс, начитавшись о достоинствах дочерних пакетов, потребовал бы от нас переделать всё следующим образом:
|
@ Это уже гораздо более красивая структура, избавляющая нас от необходимости писать Root.Object, делая расширения. Но наши ужасы на Аде 95 на этом не заканчиваются:
|
@ В то время программист использующий Аду 2005 имеет возможность написать:
|
@ и уже пьет кофе (или расслабляется мартини), пока мы возимся с редактором.
@ Некоторе время спустя программа могла бы быть расширена, чтобы приспособить равносторонние треугольники. Это могло бы быть сделано так:
|
@ Тип Equilateral_Triangle наследует все операции типа Triangle. Мы могли бы пожелать чтобы объект A_Triangle типа Triangle был равносторонним треугольником и заменить его тип на Equilateral_Triangle. Счастливый программист на Аде 2005 должен будет только изменить объявление объекта, а бедный программисты на Аде 95 должен будет изменить запросы ко всем ее примитивным операциям.
|
@ переделать на:
|
@ Есть ещё одно преимущество префиксной нотации, упомянутое во Введении. Помимо вызова функции с единственным параметром, можно непосредственно читать компонент объекта. Таким образом, мы можем написать:
|
@ Конечно, если бы мы были бы так глупы, что имели видимую переменную Area так же как функцию Area, тогда мы не могли бы вызвать функцию таким образом.
@ Но теперь предположим, что мы решаем сделать корневой тип частным так, чтобы координаты не могли быть изменены произвольно. Кроме того, мы решаем определить функции, чтобы читать их. Таким образом, мы имеем:
|
@ Используя Аду 95, мы должны были бы изменить предыдущие утверждения:
|
@ на:
|
@ или (если мы не были достаточно мудры, чтобы сделать надклассовые функции), возможно даже
|
@ тогда как в Аде 2005 мы не должны делать никаких изменений вообще!
@ Другое преимущество, упомянутое во Введении состоит в том, что при использовании ссылочных типов явное разыменование не обязательно. Предположим, что мы имеем:
|
@ В Аде 95 (предполагая, что X_Coord является видимым компонентом) мы должны написать:
|
@ В то время как на Аде 2005 мы напишем:
|
@ и это не требует изменнений если мы превращаем координаты в функции, тогда как Ада 95 утверждения должны быть изменены.
@ Есть другие структурные изменения, которые могут произойти в течение развития программы, которые намного проще, чтобы справиться с использованием префиксной нотации. Например, надклассовая операция может быть перемещена. И в случае множественных интерфейсов, которые будут описаны в следующем разделе операция могла бы быть перемещена от одного интерфейса к другому.
@ Ясно, что префиксная нотация имеет существенные выгоды и в терминах ясности программы и для обслуживания программ.
@ Предлагались и другие изменения правил нотации. Один из них состоял в том, чтобы разрешить этот механизм и для нетеговых типов, но это было отклонено на том основании, что это могло бы добавить, а не уменьшить путаницу в некоторых случаях. В любом случае, нетеговые типы не имеют надклассовых типов и, таким образом, они свойственно более просты.
@ Важно отметить, что первый параметр операции играет важную роль в префиксной нотации, мы должны гарантировать, что первый параметр - управляющий. Обработка первого параметра может казаться странной при некоторых обстоятельствах, например в случае, когда все параметры равнозначны. Таким образом, предположим, что мы имеем пакет для того, чтобы создать и управлять наборами целых чисел:
|
@ тогда мы можем применить функцию Union традиционным способом:
|
@ Объектно ориентированный маньяк может написать:
|
@ но это нарушает очевидную симметрию и скорее походит на посылку команды числу 3 прибавится к числу 2 упомянутое в начале этого обсуждения.
@ Мы надеемся, зрелый программист будет использовать OOП нотацию мудро. Возможно это поощрит более однородный стиль, в котором первый параметр всегда и везде является управляющим операндом, где это возможно. Конечно, это не может использоваться для функций, которые являются тэгом, неопределенного типа:
|
@ где нет никаких управляющих параметров. Если подпрограмма имеет только один управляющий параметр, типа Size тогда, запрос становится X.Size, и никакие круглые скобки не нужны.
@ Отметим, что префикс может и не быть только именем объекта типа X, он может быть и вызовом функции:
|
@ с очевидными результатами, как показано в комментариях.
2010-10-31 12:07:31
программа для такси скачать бесплатно . . .