И.Г. Головин - Конспект лекций по курсу Языки программирования (1161120), страница 20
Текст из файла (страница 20)
Онаспециально так сделана, чтобы старые программы выполнялись без существенногозамедления.Пример абстрактного типа данных – файловый дескриптор в системах Unix. Что такоефайловый дескриптор? Целое число.Можно реализовать стек динамически в виде списка, а можно и в виде статического массива.К скрытому ТД применим следующий набор операций: во-первых, все, что описаны, такжеоперация присваивания (именно указателей, не операция копирования), сравнения наравно/не равно.121package Stacks istype Stack is private;procedure Push(S:inout Stack; X:T);procedure Pup(S:inout Stack; X:out T);procedure IsEmpty(S: in Stack) return Boolean;private:<структура приватного типа>Type Stack is recordBody:array(1..128) of T;top:integer := 1;end record;end Stacks;use Stacks;…S:Stack;X:T;Push(S,1);Pop(S,X);S.top := 1; – ошибка!В программировании различают 2 вида копирования: поверхностное или глубокое.Различаются они только если структура данных является неплоской.
В данном случаереализация стека – плоская. Альтернативная реализация – динамический массив. В этомслучае структура данных является неплоской, и операция присваивания не пройдет.Для этого в языке Ада есть специальное слово limitedtype Stack is limited private; - целиком закрыть всю структуру данныхВ этом случае получается настоящий абстрактный тип данных.На этом закончим рассмотрение модулей в языке Ада. Начнем рассмотрение классовых ЯП.КЛАСССтруктура класса в общем случае такова:Класс:имя = имя типанабор операций = функции члены (доступ)Реализация: Структура данных = набор членов-данных … <возможно что-то еще>122Класс – это ТД и контейнер одновременно.
Иногда класс нужен нам только как контейнер.Например, в языке Java есть модуль Math. Существуют «методы доступа»: exp,…. Которые неявляются ими на самом деле. В этом случае класс нам нужен именно как контейнер.C++, C#, Java, Delphi, php, python – всё это классовые языки.class имя {<в С++ можно:>void f();<в Java обязательно:>void f(){…}}Delphi требует от нас разделения определения и реализации – это пошло еще с 70-х годов изобъектного Паскаля.SmallTalkкласс: экземпляр класса переменные (класса, экземпляра класса) методы доступа (класса, экземпляра класса)Object – Объект высшего класса (Small Talk, C#, Java, Delphi)С++: дерево объектов, в котором нет единого корня.
Может быть и лес.В Small Talk и Java есть суперкласс (Object) и подкласс – любой производный класс.В C++ есть базовые и производные классы(своя терминология).Я смеялся над терминологией Small Talk’a Почему? С точки зрения представления памяти,под-экземпляр – производный класс больше. Подкласс получается «больше» суперкласса,хотя из названия кажется, что должно быть наоборот.С точки зрения математики – терминология Small Talk понятна. Любой объектпроизводного является объектом базового. Количество элементов базового класса будетбольше количества элементов производного. Т1 и Т2 - ковариантные ТД – если один из нихявляется подмножеством другого.
Очень редко используется.Членыданные(статические)функции(статические)классыextern int a;…int a;…a=1;Если отсутствует int a; будет ошибка компоновки123class X {static int a;…int X::a = 0;..}X x;x.a; // -можно писать в С++, компилятор не запрещаетX::a; //- нужно обращаться такВ Си++ есть просто глобальные функции, а в C# всегда приходится придумывать в какойкласс поместить функцию, т.к. глобальных функций нет. Поэтому в C# придумали static class.static import Math.*; //все статические члены класса становятсявидимыми без всякого указания модуляможно писать: exp(x) вместо Math.exp(x)В Delphi статические функции тоже есть.
Вообще говоря, чтобы иметь доступ к приватнымчленам соответствующего класса.Статическое данноеЗапись – набор переменныхclass X {int a;static int foo;void f();static void g();};сonst X x;x.foo = -1; //ошибки не будет (статический член к экземпляру отношенияне имеет)Если убрать функцию g из описания класса X, то его размер не изменится.Если убрать функцию f из описания класса X, то его размер не изменится.class Y:Xvoidvoidvoid…void};{f1(){}f2(){}f3(){}f100000(){}sizeof(Y) == sizeof(X)X * const this;124X x;Обращение к нестатической функции: x.f();Члены классаЧто может быть членами класса?члены – данныеметоды, члены – функции (статические и нестатические)вложенные ТД, из которых больше всего нас будут интересовать классыСуществует ли аналог статических и нестатических членов для вложенных классов?Да, например (С++)сlass Outer{public:class inner{}//к чему он ближе? К статическому или нет,//как член класса? Конечно к статическому};Снаружи к Inner обращаться с помощью Outer::Inner,как к любым другим статическимчленам.
По синтаксису это статический тип данных или вообще не тип? Формальный ответ –посмотрите по контексту. Вообще говоря, не всегда контекст Outer::Inner однозначен.Компилятор может не видеть такую вещь в шаблонах – внутри шаблона мы обращаемся кстатическому члену.template <class T…>class sample{…T::smth;//контекст может быть не определён};Как решить, является ли что–то типом или не типом? По умолчанию статический членданных Т:: smth (только внутри шаблонов!!). Как разрешается неоднозначность? Поумолчанию это член данных, иначе нужно написать typename.Вложенные ТД (класс или перечисление, или еще что) встречаются достаточно часто,typename можно использовать и вместо ключевого слова class.Template < typename T…>//Может быть любым типом (например int)Вложенные ТД принадлежат классу целиком – полный аналог статических членов.В C# также есть вложенные классы, и они ведут себя как в С++, но есть нечто под названиемstatic (перевод плохой, но и без него бардак).
Если присутствует static, то все члены классадолжны быть статическими. Естественно, класс не может наследоваться.Static в Java по отношению к членам класса играет такую же роль, какую играет поотношению к классам. Пишется static перед именем вложенного класса.125Java:public class outer{public static class inner{}}Эквивалентно тому, что мы бы записали на C# с использованием слова static. Static в Java свойство члена.
Только вложенные классы могут быть статическими. В Java понятие staticнаиболее логично.А что такое нестатический вложенный класс? Перед ним всего – навсего не стоит ключевоеслово.class Outer{class Inner{}}То есть Inner является продолжением своего внешнего класса.Экземпляр inner находится в контексте какого–то экземпляра Out. Вопрос - а какого?class Outer{T a;class Inner{a. …}this.new Inner();}//порождает новый экземпляр Inner который привязан к thisЭто не просто отношение включения (когда объект 1го класса содержит ссылку на объектдругого класса). Класс inner всегда имеет смысл, но его this является ссылкой и на объектouter класса.inner.i = new Inner();Можно обратиться и извнеouterObjOuter.Inner obj.new Inner();Создатели java пошли дальше, у них еще появились локальные классы (что, правда, допредела запутывает ситуацию).
Однако посмотрим, что такое локальный класс? Локальныйкласс – это класс, который описан внутри блока, а блок внутри метода, а метод внутрикласса (других блоков то нет). Не является в полной мере вложенным классом (не являетсяни статическим, ни внутренним).{class local{void f((){…}}// является частью блока}126Этот класс имеет доступ к объектам, которые объявлены внутри блока.ОБЛАСТЬ ВИДИМОСТИ И ОБЛАСТЬ ДЕЙСТВИЯОбласть действия – часть программы, в которой действуют определяющие вхождения. Какправило, областью действия является блок.
Области действия обычно являютсявложенными друг в друга. Область действия связывается только с объектами данных, укоторых есть имя. Определяющее вхождение имени – объявление (в таких языках, как С,Pascal). Использующее вхождение имени – использование переменной. Обычноопределяющее вхождение в статических языках должно предшествовать использующему(за исключением случае forward-декларации).В некоторых ЯП понятие области действия более широкое.Область действия может быть больше блока? И как? Да, см. пример ниже.В Java это актуально из–за наследования, в других языках – бессмысленно.class X(){public:void f(){…}}class Y(){public:X g (){class local extended…return new local;}}Похоже на концепцию замыкания на языке C#. Переменные объемлющего блока входят взамыкание. Что это облегчает? Если в замыкание входят только читаемые переменные, топри доступе к ним можно не тратить ресурсы на синхронизацию соответствующих потоков.Как только в java появились lock–внутренние классы, появилась концепции анонимныхлокальных классов – это анонимные классы, только без имени.Пример применения внутреннего класса:Транзакция, т.к.
никакая транзакция не имеет смысла вне банковского счета.В Java отношение внутреннего класса инкапсуляцию не нарушает. Члены класса Outer неимеют доступа к внутренним членам private Inner.Специальные функции – члены класса. Компилятор знает о них кое–что дополнительное –поэтому они специальные. Компилятор умеет их автоматически вызывать (если б не умел,они не были бы специальными).Аналогичные члены есть в любых языках, только разное количество разновидностей. Онипридуманы для того, чтобы решать несколько общих проблем.1)Инициализация и уничтожение (конструктор, деструктор, финализатор)1272)3)Копирование (Конструктор, интерфейсы)Проблема преобразования (операции преобразования)В чем проблема общей инициализации? Простого обнуления недостаточно.