Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 127
Текст из файла (страница 127)
Одна из этих операций — сравнение объектов между собой. Все обьекты в языке )ача явно размещаются в динамической памяти. Большинство из них размещается в памяти с помощью оператора пви, однако в языке )ача нет оператора явного удаления объекта из памяти. Для освобождения памяти используется процедура сборки мусора. 436 Глава 11. Поддержка объектно-ориентированного программирования 11.10.2. Насладованив Язык )ача непосредственно поддерживает только одиночное наследование. Олнако . и содержит некоторый вид виртуального класса, называемый интерфейсом, который :беспечивает некий вариант множественного наследования. Определение интерфейса аналогично описанию класса, за исключением того, что интерфейс может содержать только объявления именованных констант и методов (но не определения).
Таким обраюм. интерфейс — не более чем спецификация класса. (Напомним, что абстрактный ьласс в языке С++ может иметь переменные экземпляра, и в нем можно полностью опгеделить все методы, кроме одного.) Обычно интерфейсы применяют для того, чтобы ,пределить класс, наследующий некоторые методы и переменные от родительского класса и реализующий его интерфейс. Вернемся к сценарию наследования с привлечением вплетав языка )ача, который мы кратко обсудили в разделе 11.3.5. Аплеты — это программы, интерпретируемые тгеЬ5роузерами после загрузки с ФеЬ-сервера. Вызовы вплетав включаются в НТМ).-код, :писываюший ФеЬ-страницу.
Все эти аплеты нуждаются в некоторых возможностях, которые они могут наследовать от встроенного класса Арр1ег. Когда аплет применяется зля анимации, он часто определяется как аплет, запускаемый в своем собственном потоке управления. Эта параллельность поддерживается встроенным классом с именем 2 згеаг1 Однако класс аплетов, использующий параллельность, не может наследовать .еременные и методы от обоих классов дрр1ег и Тпгеас) одновременно. Чтобы решить эту проблему, язык Зата использует встроенный интерфейс ЕцппаЬ1е, поддержиззюший интерфейс (но не реализацию) одного из методов класса Т)тгеас).
Синтаксис заголовка такого аллета поясняется следующим примером: риЬ11а а1ввв С1ос~с ехсепс)в Арр1ес зжр1ежепсв йиппаЬ1е Несмотря на то что этот класс вводится для обеспечения множественного наследования, з данном случае требуется его дальнейшее усложнение. Чтобы объект класса С1оск зал)скался параллельно, следует создать объект класса тйкеас), связанный с объектом 'ласса С1ос'к. Сообщение, управляющее параллельным выполнением объекта класса .
' эс1с, должно быть передано соответствующему объекту класса 7Ь сеась Очевидно, что такой способ слишком груб и может привести к путанице. Параллельность и потоки юыка )ата обсуждаются в главе 12. В языке )ата метод можно описать как хспв1. Эго означает, что он не может замеглаться ни в одном классе-наследнике. Когда перед определением класса указывается зарезервированное слово х-' пв1, это означает, что класс не может быть родительским ни зля одного подкласса. 11 10.3.
Динамичвсков связывание В языке С++ для того, чтобы позволить динамическое связывание, метод должен быть определен как виртуальный. В языке )ата все вызовы методов являются динамически связанными, если вызываемый метод не определен как Сдпа1 (в этом случае он не может быть замещаемым, и все связывания являются статическими). 11.10. Поддержка объектно-ориентированного программирования... 11.10А. Инкапсуляция В языке 5ача есть два вида конструкций инкапсуляции: классы н пакеты. Пакет — это логическая, а не физическая инкапсуляция. В определении любого класса можно указать, что он принадлежат конкретному пакету. Если для класса не указано нмя пакета, которому он принадлежит, то он помещается в безымянный пакет.
Пакет создает новое пространство имен. Любой метод нлн переменная, не содержащие модификатор доступа (ркхчаее, рхосеогдиз нлн рцЬ1да), имеют так называемую пакетную область видимости (рас)гайе зсоре). Все методы н переменные, не объявленные как закрытые, являются внднмымн внутри пакета, в котором онн объявлены. Это является расширением определения защищенных переменных по сравнению с языком С++, в котором защищенные члены видимы только в классе, где онн определены, н в подклассах этого класса. Пакетная область видимости — это альтернатива дружественным классам н функциям в языке С++, обеспечивающим доступ к закрытым методам н переменным экземпляра в классе для других указанных методов нлн классов.
В языке 5ача, если существуют методы н переменные, не являющиеся открытыми, которые мы хотим сделать видимыми для других классов, онн определяются как защищенные. Это скрывает нх от внешних по отношению в пакету классов, не являющихся подклассами, но помещает нх класс в один пакет с другими классами, которым мы хотим обеспечить доступ к этим переменным н методам. В действительности все не закрытые переменные н методы всех классов в пакете являются дружественными. В качестве примера применения пакета предположим, что у нас имеется класс матриц н класс векторов, н нам нужна операция, использующая объект каждого нз зтнх классов. Их переменные экземпляра можно определить как защищенные, а два класса поместить в олин н тот же пакет.
В этом случае операция, использующая объекты обоих классов, будет иметь доступ к этим переменным, которые, конечно, требуются в этом сценарии. Остается вопрос, куда поместить операцию, использующую матрицу н вектор, например, произведение матрицы н вектора. Поскольку область видимости пакета позволяет применять операцию независимо от того, определена лн она в классе матрнщ нлн в классе векторов, остается неясным, какому классу она принадлежит. Она может быть описана в одном нз двух классов нлн в отдельном классе внутри пакета.
1 1.10.5. Оцвнка Способы полдержкн объектно-ориентированного программирования в языках )ача н С++ в целом похожи, но различаются несколькими важнымн аспектами. Сохраняя последовательную приверженность объектно-ориентированным принципам, вследствие недостатка функций язык )ача не позволяет использовать классы, не имеющие роднтелы скнх классов.
Он также использует динамическое связывание в качестве "нормального" подхода к связыванию вызовов метода с его определением. Управление доступом к содержимому определения класса проще, чем запуганное управление доступом в языке С++, которое варьируется от управления доступом прн наследовании до дружественных функций. 490 Глава 11. Поддержка объектно-ориентированного программирования 8 1.11. Поддержка обьектно-ориентированного программирования в языке Ада 95 Язык Ада 95 происходит от языка Аг(а 83, но имеет некоторые сушественные дополнения. В этом разделе представлен краткий обзор дополнений, разработанных для поддержки объектно-ориентированного программирования.
Поскольку в языке Ада 83 уже были конструкции лля построения абстрактных типов данных, которые обсуждались в главе 10, остается рассмотреть свойства, необходимые для поддержки наследования и динамического связывания. Требование минимальных изменений структуры типов и пакетов языка Ада 83, а также как можно более широкое использование статической проверки типов было одной из главных целей при разработке этих свойств.
11.11.1. Общив свойства Классы в языке Ада 95 представляют собой новую категорию, называемую мечеными типами (ьзййед гурез), которые могут быть либо записями, либо закрытыми типами. Они инкапсулируются в пакетах, что позволяет компилировать их отдельно. Мечеными эти типы называются потому, что каждый объект такого типа неявно содержит системную метку ((ай), которая служит признаком его типа. Подпрограммы, определяющие операции с мечеными типами, помешаются в тот же перечень объявлений, что и объявление типа. Рассмотрим следуюший пример: рао)саде РЕКЯО(Ч РКС 1е Фуре РЕВЯОХ 1в таддег$ рк1чаке ркооег(оке 01ЯРьАУ(Р: 1п оив РЕКЯОИ) г рк1часе куре РЕКЯО(Ч 1в саддео кеоокс( (ЧА(ЧЕ: ЯТК1(ЧО (1 ..
30]; АООКЕЯЯ : ЯТК1НО(1..30); АОК : 1(ЧТЕОКК( ( аг епа РККЯОК РКЯГ Этот пакет определяет тип РЕКЯОХ, который можно использовать как сам по себе, так и в качестве родительского класса по отношению к другим производным классам. В отличие от языка С++ в языке Ада 95 нет неявных вызовов конструкторов или леструкторов. Эти подпрглраммы можно написать, но они должны быть явно вызваны программистом. 11.11.2. Наследованив Язык Аг)а 83 имеет ограниченный вид наследования для своих производных типов и подтипов.
В обоих случаях новый тип можно определить на основе уже сушествуюшего типа, однако единственная модификация, которая позволяется при этом, — ограничение диапазона значений нового типа. Производные классы в языке Аба 95 основаны на меченых типах. Новые сущности добавляются к наследуемым сущностям с помощью опрелеления записи. Рассмотрим следуюший пример: Я91 1 1.1 1. Поддержко объектно-ориентировонного прогроммировония... мйв)з РЕВЯО(Ч РКОг иве РЕВЯОК РКО) рао)саде ЯТРРЕ(ЧТ РКО йв суре ЯТООЕИТ Ев пем РЕВЯО)Ч мхе)з геоогс1 СВАРЕ Р01)(Т АЧЕВАОЕ : Г10АТ) СВАРЕ ЬЕЧЕЬ: 11)ТЕОЕВ) О об) ргооейиге 01ЯРЬАУ (ЯТ: Еп ЯТООЕг)Т] епс( ЯТОРЕ(ЧТ РКО; В этом примере производный тип ЯТОРЕ(ЧТ имеет сушности из его родительского класса РЕВЯО)( нарялу с новыми сушностями АНКАРЕ Р01КТ АЧЕВАОЕ и СВАРЕ ЬЕчЕь.
Он также переопределяет пропедуру 01Я РЬАУ. Этот новый класс определяется в отдельном пакете, чтобы можно было вносить в него изменения без повторной компиляпии пакета, содержащего родительский класс. С помошью этого механизма наслелования невозможно предотвратить включение сущностей родительского класса в производный класс. Следовательно, производные классы могут лишь расширять родительские классы, и поэтому являются подтипами. Предположим, у нас есть следующие определение: Р1: РЕВЯОЛ) г Я1 : ЯТООЕМТ; ГВЕО : РЕВЯО)(:= ("ГВЕР", "321 МЧ1Ьгггу Ьапе", 35); ГВЕ001Е : ЯТООЕНТ := ("ГВЕ001Е", ?625 Ма1п ЯС.", 20, 3.25, 3); Поскольлу ЯТООЕ)ЧТ является подтипом типа РЕВЯО)(, присваивание Р1 := ГВЕ001Е) должно быть законным и является таковым.