Сравнение Языков Программирования
Материал из eSyr's wiki.
(→ADA) |
(→ADA) |
||
Строка 420: | Строка 420: | ||
'''end'''; | '''end'''; | ||
- | '''finally-блока в Аде таки нету.''' | + | '''finally-блока в Аде таки нету.''' Однако он [http://stackoverflow.com/questions/4804135/best-practice-for-implementing-in-ada-2005-or-2012-an-equivalent-of-the-java-f имитируется]. |
Отлов исключения так же может иметь такой вид: | Отлов исключения так же может иметь такой вид: |
Версия 11:01, 13 января 2013
На этой страничке собираются материалы, которые могут помочь при подготовке к экзамену по языкам программирования.
ЯП из курса: C, C++, Java, C#, Pascal, Delphi, Оберон-2, Модула-2, Ада (83 и 95 стандарты)
Полезные ссылки:
Энциклопедия языков программирования
Немножно рекламное сравнения большинства языков
План (краткий, взят из методички Головина, подробный см. в самой методичке):
Базисные типы данных в языках программирования: простые и составные типы данных, операции над ними
ADA
- Integer
- Размер не фиксирован.
- Character
- Как я понял, существует несколько разновидностей (зависит от размера) и является особым перечислимым типом (Enumeration)
- String
- Массив Character фиксированной длины. Так же есть стандартные пакеты, реализующие строки квазистатической и динамической длины.
- Floating point
- Эти типы обычно определяются вручную в виде конструкции, где Num_Digits указывает минимальную погрешность:
digits Num_Digits
- Fixed Point
- Эти типы также обычно определяются вручную в виде конструкции, где Delta означает погрешность:
delta Delta range Low .. High
ОБЕРОН-2 и ОБЕРОН:
- Отличия
- В Оберон-2 добавлены
- связанные с типом процедуры;
- экспорт только для чтения;
- открытые массивы в качестве базового типа для указателей;
- оператор with с вариантами;
- оператор for.
- Основные типы
- 1. BOOLEAN логические значения TRUE и FALSE
- 2. CHAR символы расширенного набора ASCII (0X .. 0FFX)
- 3. SHORTINT целые в интервале от MIN(SHORTINT) до MAX(SHORTINT)
- 4. INTEGER целые в интервале от MIN(INTEGER) до MAX(INTEGER)
- 5. LONGINT целые в интервале от MIN(LONGINT) до MAX(LONGINT)
- 6. REAL вещественные числа в интервале от MIN(REAL) до MAX(REAL)
- 7. LONGREAL вещественные числа от MIN(LONGREAL) до MAX(LONGREAL)
- 8. SET множество из целых от 0 до MAX(SET)
Типы от 3 до 5 - целые типы, типы 6 и 7 - вещественные типы, а вместе они называются числовыми типами. Эти типы образуют иерархию; больший тип поглощает меньший тип:
LONGREAL >= REAL >= LONGINT >= INTEGER >= SHORTINT
- Примеры объявлений переменных
- i, j, k: INTEGER
- a: ARRAY 100 OF REAL
- Операции
+, -, *, /, DIV, MOD
- Операции над множествами
- + объединение
- - разность (x - y = x * (-y))
- x пересечение
- / симметрическая разность множеств (x / y = (x-y) + (y-x))
- Отношения
=, #, <, <=, >, >=, IN(принадлежность множеству),IS(проверка типа)
- Пример присваивания
i := 0
- Тип Запись
RECORD day, month, year: INTEGER END
Массивы. Длина массива - статический или динамический атрибут.
Си++: длина массива - только статический аттрибут.
Оберон, Модула-2: динамический аттрибут только для формальных параметров, в остальных случаях - статический.
Ада, Java, C#: может быть и тем и другим.
Замечание из методички:
в языках Оберон и Модула-2 длина формальных
параметров — открытых массивов является динамическим атрибутом.
В других случаях длина массива — статический атрибут.
В Аде формальные параметры неограниченных типов-массивов также имеют динамический
атрибут-длину (равно как и динамические массивы-локальные переменные).
Пример динамического массива в языке Java (или C#):
void f(int N) {
byte [] dynArray = new byte [N];
// ...обработка ...
}
Управление памятью
Классы памяти:
Статическая Всё что связано со словом «статический» размещается в блоке статической памяти. Время жизни – от начала программы либо момента первого входа в блок, и до конца программы.
Квазистатическая Квазистатическая память связана с понятием блока: переменные связана с этим блоком (от момента объявления, точнее, прохода code flow через объявление, до выхода из блока). Размещаются в стеке. Еще автоматической называют (автоматическая переменная).
Динамическая Время жизни зависит от процедур (ручное управление памятью) или от сборщика мусора.
ОБЕРОН И ОБЕРОН-2
Элементы массива обозначаются индексами, которые являются целыми числами от 0 до длины массива минус 1.
- ТипМассив = ARRAY [Длина {"," Длина}] OF Тип.
- Длина = КонстантноеВыражение.
Тип вида
ARRAY L0, L1, ..., Ln OF T
понимается как сокращение
ARRAY L0 OF ARRAY L1 OF ... ARRAY Ln OF T
Массивы, объявленные без указания длины, называются открытыми массивами. Они могут использоваться только в качестве базового типа указателя, типа элементов открытых массивов и типа формального параметра
Указатели
Ада, C, C++, C#, Delphi, Оберон
Указатели языка Ада 83 ссылаются только на объекты из динамической памяти. Указатель языка Си++ может ссылаться на любой объект данных (динамический, локальный, статический), что может приводить к труднообнаружимым ошибкам.
Также в языке Ада отсутствует адресная арифметика (арифметические операции над указателями), что также уменьшает вероятность появления ошибки работы с памятью.
В языке Оберон(и Оберон-2) указатель может быть объявлен только на массив или запись. ТипУказатель = POINTER TO Тип. Любая переменная-указатель может принимать значение NIL, которое не указывает ни на какую переменную вообще.
В Java явных указателей нет.
Операторный базис языков программирования. Управление последовательностью вычислений
ADA
Джентльменский набор:
if condition then statement; elseif enother_condition then enother_statement; ... else last_one_statement; end if;
case X is when constant1 => stetement1; when constant2 | constant3 => statement2_and3; ... when others => other_statement; end case;
return; -- for procedures return Value; -- for functions
goto Label Dont_Do_Smth; <<Label>>
Циклы устроены посложнее:
Endless_Loop : loop Do_Something; end loop Endless_Loop;
While_Loop : while X <= 5 loop X := Calculate_Something; end loop While_Loop;
Until_Loop : loop X := Calculate_Something; exit Until_Loop when X > 5; end loop Until_Loop;
Exit_Loop : loop X := Calculate_Something; exit Exit_Loop when X > 5; Do_Something (X); end loop Exit_Loop;
For_Loop : for I in Integer range 1 .. 10 loop Do_Something (I) end loop For_Loop;
Процедурные абстракции
Перегрузка операций
Ада 83, Ада 95, Си++, Java, Delphi, C#
Понятие «перегрузка» означает, что одному имени в одной области видимости может соответствовать несколько определений. В современных языках программирования перегружаться могут только имена подпрограмм, но не типов, переменных, модулей. Пример на языке Си++:
class X { public: void f(); void f (int) }; X a; a.f(); // первая функция a.f(0); // вторая функция
Отличие перегрузки от замещения состоит во-первых, в том, что перегрузка обрабатывается статически (на этапе трансляции), в во-вторых, при замещении речь идет о разных областях видимости: базовый класс с объявлением виртуального метода (объемлющая область видимости) и производный класс с замещающим методом (вложенная область видимости).
Определение новых типов данных. Логические модули. Классы
ADA
В Аде вообще типы принято определять вручную, пользуясь конструкциями type и subtype. Например:
type Short is range -128 .. +128 type Index is range 0 .. 256 type My_String is array ( Index range <> ) of Character -- My_String - это массив, индексируемый типом Index в неизвестных пока границах, состоящий из Character subtype String_10 is My_String ( 0 .. 10 ); -- Подтип типа My_String, состоящий из 11 элементов. type Money is delta 1/100 range 0.0 ... 10000.0
Ключевое слово Limited означает, что у новоявленного типа нет стандартного оператора присваивания до тех пор, пока пользователь сам его не определит.
В языке Ada есть мощный механизм пакетов, и этим он, несмотря на то, что основан на Pascal, совсем на него не похож. Пакеты заимствованы из других языков. Они похожи на классы тем, что являются средством абстракции, позволяющем инкапсулировать сложность внутри пакета, предоставив наружу только интерфейс. Ладно, к сути.
Каждый пакет физически разделён на две части.
-- Интерфейс package Points is type Point is record x: Integer; y: Integer; end record; zero: constant Point := (0, 0); procedure setToZero(point: in out Point); function dotProduct(point1: in Point; point2: in Point) return Integer; end Points;
-- Реализация package body Points is procedure setToZero(point: in out Point) is begin point := zero; end setToZero; function dotProduct(point1: in Point; point2: in Point) return Integer is begin return point1.x * point2.x + point1.y * point2.y; end setToZero; end Points;
Ada имеет средства разграничения доступа. Всё, что следует за спецификатором private, не будет доступно при импорте пакета.
-- Интерфейс package Points is type Point is private; -- Это ключевое слово как бы намекает. zero: constant Point; -- Тут тоже неявный private. procedure setToZero(point: in out Point); function dotProduct(point1: in Point; point2: in Point) return Integer; private type Point is record x: Integer; y: Integer; end record; zero: constant Point := (0, 0); end Points;
Вне пакета можно будет объявить переменные типа «Point», но все действия будут ограничены присваиваниями, сравнениями на равенство и проверками принадлежности (нужно описать подробнее). Поэтому в пакет надо бы добавить «конструктор», если, конечно, предполагается возможная инициализация этих структур вне пакета. Если стандартная реализация этих операций не устраивает, можно использовать limited private, который в остальном ничем от private не отличается, но этих операций не позволяет.
Реализация может также иметь часть-инициализацию. Это всё, что после begin.
package body Points is procedure setToZero(point: in out Point) is begin point := zero; end setToZero; function dotProduct(point1: in Point; point2: in Point) return Integer is begin return point1.x * point2.x + point1.y * point2.y; end setToZero; begin Ada.Text_IO.Put_Line("Package ready!"); end Points;
Пакеты можно расширять. Взять и определить пакет Points.RandomDistributions, в нём можно пользоваться всем, что объявлено в пакете-родителе. Пакет можно сделать недоступным вне своей иерархии.
private package Points.internalThing is <...>
При подключении потомка родитель-пакет подключается автоматически.
О подключениях. Подключить пакет можно с помощью конструкции with.
with Points.RandomDistributions;
После этого можно будет пользоваться ввсем, что в пакете лежит, через точечную нотацию. Если же вызовов слишком много, то можно влить содержимое пакета в текущую область видимости с помощью use (только после подключения!).
use Points.RandomDistributions;
В случае конфликтов имён придётся-таки предварять каждое обращение именем пакета.
ОБЕРОН И ОБЕРОН-2
В Обероне-2 стандартная процедура NEW используется, чтобы распределить блоки данных в свободной памяти. Нет, однако, никакого способа явно освободить распределенный блок. Взамен Оберон-среда использует сборщик мусора чтобы найти блоки, которые больше не используются и сделать их снова доступными для распределения.
- Расширение типов
Наиболее важным добавлением(от-но Modula-2) является механизм расширенных типов записи. Он позволяет конструировать новые типы на основе уже существующих и задает определенную степень совместимости между новыми и старыми типами. Предположим, что у нас имеется тип
T = RECORD x,y: INTEGER END
В дополнение к существующим полям могут быть заданы новые:
T0 = RECORD (T) z: REAL END T1 = RECORD (T) w: LONGREAL END
Здесь определяются типы с полями x,y,z и x,y,w соответственно. Мы говорим, что тип T’
T’ = RECORD (T) <описание_полей> END
является (прямым) расширением типа T, и наоборот, T называется (прямым) базовым (base) типом для T’.
Инкапсуляция и абстрактные типы данных
Модульность и раздельная трансляция
Раздельная трансляция
C, C++
Раздельная трансляция означает то, что программа разбивается на части — физические модули или единицы компиляции. Каждая единица может или обязана транслироваться отдельно от остальных. Независимая раздельная трансляция означает то, что транслятор не обладает информацией об уже оттранслированных единицах и поэтому не может проверить корректность межмодульных связей.
Модульность
ОБЕРОН И ОБЕРОН-2
- Модуль - совокупность объявлений констант, типов, переменных и процедур вместе с последовательностью операторов, предназначенных для присваивания начальных значений переменным. Модуль представляет собой текст, который является единицей компиляции.
Модуль = MODULE идент ";" [СписокИмпорта] ПоследовательностьОбъявлений [BEGIN ПоследовательностьОператоров] END идент ".". СписокИмпорта = IMPORT Импорт {"," Импорт} ";". Импорт = [идент ":="] идент.
Список импорта определяет имена импортируемых модулей. Последовательность операторов после символа BEGIN выполняется, когда модуль добавляется к системе (загружается). Это происходит после загрузки импортируемых модулей. Отсюда следует, тот циклический импорт модулей запрещен. Отдельные (не имеющие параметров и экспортированные) процедуры могут быть активированы из системы. Эти процедуры служат командами.
MODULE Trees; (* экспорт: Tree, Node, Insert, Search, Write, Init *) IMPORT Texts, Oberon; (* экспорт только для чтения: Node.name *)
TYPE Tree* = POINTER TO Node; Node* = RECORD name-: POINTER TO ARRAY OF CHAR; left, right: Tree END;
VAR w: Texts.Writer;
PROCEDURE (t: Tree) Insert* (name: ARRAY OF CHAR); VAR p, father: Tree; BEGIN p := t; REPEAT father := p; IF name = p.name^ THEN RETURN END; IF name < p.name^ THEN p := p.left ELSE p := p.right END UNTIL p = NIL; NEW(p); p.left := NIL; p.right := NIL; NEW(p.name, LEN(name)+1); COPY(name, p.name^); IF name < father.name^ THEN father.left := p ELSE father.right := p END END Insert;
PROCEDURE (t: Tree) Search* (name: ARRAY OF CHAR): Tree; VAR p: Tree; BEGIN p := t; WHILE (p # NIL) & (name # p.name^) DO IF name < p.name^ THEN p := p.left ELSE p := p.right END END; RETURN p END Search;
PROCEDURE (t: Tree) Write*; BEGIN IF t.left # NIL THEN t.left.Write END; Texts.WriteString(w, t.name^); Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf); IF t.right # NIL THEN t.right.Write END END Write;
PROCEDURE Init* (t: Tree); BEGIN NEW(t.name, 1); t.name[0] := 0X; t.left := NIL; t.right := NIL END Init;
BEGIN Texts.OpenWriter(w) END Trees.
Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон.
Исключительные ситуации и обработка ошибок
Исключения и блоки try {} catch {} finally {}. Семантика возобновления и семантика завершения.
Семантика возобновления: после обработки исключения управление может вернуться непосредственно в точку, где возникло исключение (варианты: на следующий оператор или на любой оператор из того же блока). Пример языка c семантикой возобновления: Visual Basic.
Семантика завершения: после возникновения исключения блок, в котором оно возникло, обязательно завершается. Обработка исключения происходит в блоках, вызвавших блок с исключением. Пример языка с семантикой завершения: Си++.
catch (в delphi - except) - то что будет выполнено в случае ошибки в блоке try. finally - то что будет выполнено в любом случае, вне зависимости от того что произошло в блоке try.
ADA
Создание исключения:
New_Exception: exception;
Выбрасывание исключения:
raise New_Exception;
Отлов исключения:
begin Rise_Exception; exception when New_Exception => Do_Smth; end;
finally-блока в Аде таки нету. Однако он имитируется.
Отлов исключения так же может иметь такой вид:
when Error: Error_Name =>
Однако, что он означает я до конца не понял, но на экзамене это вряд ли нужно будет. Кому интересно, брал здесь.
Наследование типов и классов
Динамический полиморфизм
Абстрактные классы и интерфейсы
Абстрактный тип данных (АТД) — это тип с полностью инкапсулированной структурой. Использовать объекты АТД возможно только при помощи явно определенных в интерфейсе типа операций. Абстрактный класс (АК) — это класс, содержащий хотя бы один абстрактный метод.
Прямой связи между АК и АТД нет. АТД может быть абстрактным классом, а может и не быть. Аналогично, АК может иметь инкапсулированную структуру, а может и не иметь.
Множественное наследование
Динамическая идентификация типа
Понятие о родовых объектах. Обобщенное программирование
ADA
Note to C++ programmers: generic units are similar to C++ templates. Ada Programming
Объявляем шаблон:
generic type Element_T is private; -- Generic formal type parameter procedure Swap (X, Y : in out Element_T);
Для его использования необходимо создать объект нужного типа:
procedure Swap_Integers is new Swap (Integer);
Возможна перегрузка:
procedure Instance_Swap is new Swap (Float); procedure Instance_Swap is new Swap (Day_T);
- Оператор loop определяет повторное выполнение последовательности операторов.
- Операторы with выполняют последовательность операторов в зависимости от результата проверки типа и применяют охрану типа к каждому вхождению проверяемой переменной внутри этой последовательности операторов.
Итоговая таблица
Если в таблице указан знак вопроса, то либо этого языка не было в списке языков в задании, либо информация отсутствует.
C | C++ | C# | Java | Pascal | Delphi | Оберон | Оберон-2 | Modula-2 | Ada83 | Ada95 | |
---|---|---|---|---|---|---|---|---|---|---|---|
есть оператор перехода «goto метка» | есть | есть | есть | нет | есть | есть | нет | нет | нет | есть | есть |
есть try-finally | нет | нет | есть | нет??? | нет исключений | есть | нет | нет | нет | нет | нет |
есть понятие динамического связывания подпрограмм (методов класса) | ? | есть | есть | есть | ? | есть | нет | есть | нет | нет | есть |
Тип Запись | есть | есть | есть | есть | есть | есть | |||||
Оператор loop | есть | есть | есть | есть | есть | ||||||
Оператор with | есть | есть | есть | ||||||||
Процедурное программирование | есть | есть | есть | есть | есть | есть | есть | есть | есть | есть | |
Модульное программирование | ч/и | ч/и | и | и | и | есть | есть | есть | |||
АТД | нет | есть | есть | есть | есть | есть | есть | ||||
Расширяющее программирование | нет | и | и | и | и | есть | есть | ||||
ООП | нет | есть | есть | есть | есть | и | есть | нет | есть? | ||
Компонентное программирование | и | и | и | и | и | и | и | ||||
Композиционное программирование | нет | нет | нет | нет | нет | ч/и | ч/и | ||||
Обобщенное программирование | нет | и | и | нет | нет | нет | нет | есть | есть | ||
Параллельное программирование | нет | нет | есть | есть | нет | нет | нет | ||||
Рефлективное программирование | нет | и | есть | и | и | и | и |
- ч/и - частично имитируется
- и - имитируется