Редактирование: Сравнение Языков Программирования
Материал из eSyr's wiki.
Внимание: Вы не представились системе. Ваш IP-адрес будет записан в историю изменений этой страницы.
ПРЕДУПРЕЖДЕНИЕ: Длина этой страницы составляет 43 килобайт. Страницы, размер которых приближается к 32 КБ или превышает это значение, могут неверно отображаться в некоторых браузерах. Пожалуйста, рассмотрите вариант разбиения страницы на меньшие части.
Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия | Ваш текст | ||
Строка 1: | Строка 1: | ||
На этой страничке собираются материалы, которые могут помочь при подготовке к экзамену по языкам программирования. | На этой страничке собираются материалы, которые могут помочь при подготовке к экзамену по языкам программирования. | ||
- | ЯП из курса: C, C++, Java, C#, Pascal, Delphi, Оберон-2, Модула-2, Ада (83 и 95 стандарты) | + | ЯП из курса: C, C++, Java, C#, Pascal, Delphi, Оберон-2, Модула-2, Ада (83 и 95 стандарты) |
Полезные ссылки: | Полезные ссылки: | ||
- | * [[w:Сравнение языков программирования|Сравнение ЯП в википедии]] | ||
- | * [http://progopedia.ru/ Энциклопедия языков программирования] | ||
- | * [http://citforum.ru/programming/cpp/aglav.shtml Книжка Страуструпа] | ||
- | * [https://habrahabr.ru/post/161205/ Ликбез по типизации в языках программирования / Хабрахабр] | ||
- | + | [http://ru.wikipedia.org/wiki/%D1%F0%E0%E2%ED%E5%ED%E8%E5_%FF%E7%FB%EA%EE%E2_%EF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%FF Сравнение ЯП в википедии] | |
- | + | [http://progopedia.ru/ Энциклопедия языков программирования] | |
- | + | [http://home.perm.ru/strannik/st_txt_prog_02.html/ Немножно рекламное сравнения большинства языков] | |
+ | План (краткий, взят из методички Головина, подробный см. в самой [http://cmcmsu.no-ip.info/download/pl.exam.variants.pdf методичке]): | ||
+ | |||
+ | == Базисные типы данных в языках программирования: простые и составные типы данных, операции над ними == | ||
+ | === ADA === | ||
; Integer: Размер не фиксирован. | ; Integer: Размер не фиксирован. | ||
; Character: Как я понял, существует несколько разновидностей (зависит от размера) и является особым перечислимым типом (Enumeration) | ; Character: Как я понял, существует несколько разновидностей (зависит от размера) и является особым перечислимым типом (Enumeration) | ||
; String: Массив '''Character''' фиксированной длины. Так же есть стандартные пакеты, реализующие строки квазистатической и динамической длины. | ; String: Массив '''Character''' фиксированной длины. Так же есть стандартные пакеты, реализующие строки квазистатической и динамической длины. | ||
- | ; Floating point: Эти типы обычно определяются вручную в виде конструкции, где Num_Digits указывает | + | ; Floating point: Эти типы обычно определяются вручную в виде конструкции, где Num_Digits указывает минимальную погрешность: |
'''digits''' Num_Digits | '''digits''' Num_Digits | ||
Строка 40: | Строка 40: | ||
'''end''' | '''end''' | ||
- | + | === ОБЕРОН и ОБЕРОН-2: === | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | === ОБЕРОН и ОБЕРОН-2 === | + | |
- | + | ||
; Отличия: | ; Отличия: | ||
; В Оберон-2 добавлены: | ; В Оберон-2 добавлены: | ||
Строка 100: | Строка 68: | ||
+, -, *, /, DIV, MOD | +, -, *, /, DIV, MOD | ||
;Операции над множествами | ;Операции над множествами | ||
- | : + объединение | + | :+ объединение |
- | : - разность (x - y = x * (-y)) | + | :- разность (x - y = x * (-y)) |
- | : | + | :x пересечение |
- | : / симметрическая разность множеств (x / y = (x-y) + (y-x)) | + | :/ симметрическая разность множеств (x / y = (x-y) + (y-x)) |
;Отношения | ;Отношения | ||
- | =, # | + | =, #, <, <=, >, >=, IN(принадлежность множеству),IS(проверка типа) |
;Пример присваивания: | ;Пример присваивания: | ||
i := 0 | i := 0 | ||
Строка 112: | Строка 80: | ||
day, month, year: INTEGER | day, month, year: INTEGER | ||
END | END | ||
- | |||
- | === Modula-2 === | ||
- | |||
- | Порядковые: CARDINAL CHAR INTEGER BOOLEAN <br> | ||
- | Битовое множество BITSET (Величина может зависеть от реализации. Например, 32 бита) <br> | ||
- | Плавающая точка: REAL LONGREAL (Подчиняются IEEE, но зависят от реализации. К примеру, возможно REAL = LONGREAL = double) <br> | ||
- | Процедурный тип PROC <br> | ||
- | |||
- | === Java === | ||
- | |||
- | Java — это язык со статической типизацией. Это значит, что каждой переменной и каждому выражению соответствует тип, известный на этапе компиляции. | ||
- | |||
- | Типы подразделяются на две категории (если не считать null, см. чуть дальше). | ||
- | |||
- | Примитивные (primitive) типы: | ||
- | * boolean (true или false) | ||
- | * Числовые типы: | ||
- | ** Целые числа: | ||
- | *** Знаковые: byte, short, int, long (8-, 16-, 32-, 64-битные). | ||
- | *** Беззнаковый 16-битный: char (код символа в UTF-16<ref>Была правка UTF-16 → Unicode. Откатил. Пояснил на странице обсуждения.</ref>). | ||
- | ** Числа с плавающей точкой: float, double (32-, 64-битные; IEEE 754). | ||
- | |||
- | Ссылочный (reference) тип: | ||
- | * Классы, интерфейсы, массивы. | ||
- | |||
- | Также существует специальный тип null. | ||
- | |||
- | Объектом в Java считается экземпляр класса или массив. Значением ссылочного типа является ссылка на объект (или специальное значение null). Значение переменной ссылочного типа можно изменить, в отличии от C++. | ||
- | |||
- | Все объекты (включая массивы) обладают методами класса Object (java.lang.Object) (иначе говоря, с т. з. Java-программиста все объекты *наследуют* методы класса Object). Строковые литералы (например, "Hello world!") являются объектами типа String (иначе говоря, экземплярами класса String). | ||
- | |||
- | Операции над простыми типами почти идентичны C/C++, однако могут выбрасывать исключения. Конкатенация строк: "Hello " + "world!" (может принимать в качестве одного из аргументов не только строку, но и любой из целых типов). | ||
- | |||
- | Больше информации о типах, значениях и переменных: http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html . | ||
- | |||
- | === C++ === | ||
- | |||
- | ; Целые типы: | ||
- | : char - размер как для хранения символа, определяется машиной (обычно байт) | ||
- | : short - размер, соответствующий целой арифметике на данной машине (обычно, слово) | ||
- | : int | ||
- | : long | ||
- | : long long | ||
- | Для всех целых типов есть unsigned аналоги. По умолчанию - знаковые (так что, например, signed int - то же самое, что int). | ||
- | Исключение - char. Его знаковость/беззнаковость зависит от реализации. | ||
- | ; С плавающей точкой: | ||
- | : float | ||
- | : double | ||
- | : long double | ||
- | 1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)<br> | ||
- | sizeof(float) <= sizeof(double) <= sizeof(long double) | ||
- | |||
- | '''const''' <тип> <имя_переменной> = <значение>; | ||
- | // Значение переменной не может изменяться после инициализации (инициализация обязательна). | ||
- | |||
- | ; Aрифметические операции: | ||
- | : + (плюс, унарный и бинарный) | ||
- | : - (минус, унарный и бинарный) | ||
- | : * (умножение) | ||
- | : / (деление) | ||
- | : Над целыми - операция % получения остатка: 7%2 = 1 | ||
- | ; Операции сравнения: | ||
- | : == (равно) | ||
- | : != (не равно) | ||
- | : <, >, <=, >= | ||
- | |||
- | Также логические операции ( &&, || ), побитовые операции(&, |, ^, <<, >>), а так же сокращённые формы многих операций: +=, -=, %=, &&=, ||=, &=, ++, -- (последние два имеют префиксные и постфиксные формы) и им подобные. | ||
- | |||
- | При присваивании и арифметических операциях C++ выполняет все осмысленные преобразования между основными типами, чтобы их можно было сочетать без ограничений. | ||
- | |||
- | ; Производные типы: | ||
- | : * - указатель на | ||
- | : *const - константный указатель на | ||
- | : & - ссылка на | ||
- | : [] - вектор (одномерный массив), индексация с 0 | ||
- | : () - функция, возвращающая | ||
- | : Унарное & - операция взятия адреса | ||
- | |||
- | Например:<br> | ||
- | char* p // указатель на символ<br> | ||
- | char *const q // константный указатель на символ<br> | ||
- | char v[10] // вектор из 10 символов<br> | ||
- | char c; p = &c; // p указывает на c | ||
=== C# === | === C# === | ||
- | + | ; Встроенные типы | |
- | ; Встроенные типы | + | |
: 1. sbyte, byte - 8-битное целое число | : 1. sbyte, byte - 8-битное целое число | ||
: 2. short, ushort - 16-битное целое число | : 2. short, ushort - 16-битное целое число | ||
Строка 206: | Строка 90: | ||
: 6. bool - 8-битное логическое значение | : 6. bool - 8-битное логическое значение | ||
: 7. char - 16-битный знак Юникода | : 7. char - 16-битный знак Юникода | ||
- | : 8. decimal - 128-битный точный дробный или целочисленный, который может представлять десятичные числа с 29 значащими цифрами | + | : 8. decimal - 128-битный точный дробный или целочисленный, который может представлять десятичные числа с 29 значащими цифрами |
- | + | Особняком стоят: | |
- | Особняком стоят | + | |
: 9. string - последовательность знаков | : 9. string - последовательность знаков | ||
: 10. object - базовый тип для всех остальных типов | : 10. object - базовый тип для всех остальных типов | ||
;Структуры и классы | ;Структуры и классы | ||
- | В C# структуры являются урезанной версией класса. Память под структуры наравне с простыми типами выделяется на стеке (если | + | В C# структуры являются урезанной версией класса. Память под структуры наравне с простыми типами выделяется на стеке (если конечно они не являются частью объекта - память под объекты всегда выделяется на куче). Ограничения на структуры: |
- | : 1. Структура не может быть | + | : 1. Структура не может наследоваться и не может быть унаследована ни от чего, кроме типа object. |
- | : 2. В структуре нельзя явно определить конструктор умолчания | + | : 2. В структуре нельзя явно определить конструктор умолчания. |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | ; | + | ;Референциальные типы |
- | : | + | : Классы, массивы, интерфейсы. Располагаются на куче. |
- | + | ||
- | + | ||
- | + | ||
- | == Массивы | + | === Массивы. Длина массива - статический или динамический атрибут. === |
- | + | <b>Си++</b>: длина массива - только статический атрибут. <br> | |
- | + | <b>Оберон</b>, <b>Модула-2</b>: динамический атрибут только для формальных параметров, в остальных случаях - статический. <br> | |
- | + | <b>Ада</b>, <b>Java</b>, <b>C#</b>: может быть и тем и другим. <br> | |
- | + | ||
<br> | <br> | ||
- | + | <b>Замечание из методички</b>: <br> | |
в языках Оберон и Модула-2 длина формальных параметров — открытых массивов является динамическим атрибутом. <br> | в языках Оберон и Модула-2 длина формальных параметров — открытых массивов является динамическим атрибутом. <br> | ||
В других случаях длина массива — статический атрибут. <br> | В других случаях длина массива — статический атрибут. <br> | ||
В Аде формальные параметры неограниченных типов-массивов также имеют динамический атрибут-длину (равно как и динамические массивы-локальные переменные). <br> | В Аде формальные параметры неограниченных типов-массивов также имеют динамический атрибут-длину (равно как и динамические массивы-локальные переменные). <br> | ||
<br> | <br> | ||
- | + | <b>Пример</b> динамического массива в языке Java (или C#): <br> | |
- | + | void f(int N) { <br> | |
- | + | byte [] dynArray = new byte [N]; <br> | |
- | + | // ...обработка ... <br> | |
- | + | } <br> | |
+ | |||
+ | === Управление памятью === | ||
+ | Классы памяти: | ||
+ | |||
+ | '''Статическая''' | ||
+ | Всё что связано со словом «статический» размещается в блоке статической памяти. Время жизни – от начала программы либо момента первого входа в блок, и до конца программы. | ||
+ | |||
+ | '''Квазистатическая''' | ||
+ | Квазистатическая память связана с понятием блока: переменные связана с этим блоком (от момента объявления, точнее, прохода code flow через объявление, до выхода из блока). Размещаются в стеке. Еще автоматической называют (автоматическая переменная). | ||
+ | |||
+ | '''Динамическая''' | ||
+ | Время жизни зависит от процедур (ручное управление памятью) или от сборщика мусора. | ||
=== ОБЕРОН И ОБЕРОН-2 === | === ОБЕРОН И ОБЕРОН-2 === | ||
Строка 263: | Строка 149: | ||
Массивы, объявленные без указания длины, называются открытыми массивами. Они могут использоваться только в качестве базового типа указателя, типа элементов открытых массивов и типа формального параметра. | Массивы, объявленные без указания длины, называются открытыми массивами. Они могут использоваться только в качестве базового типа указателя, типа элементов открытых массивов и типа формального параметра. | ||
Длина формальных параметров — открытых массивов является динамическим атрибутом. | Длина формальных параметров — открытых массивов является динамическим атрибутом. | ||
- | |||
- | === Modula-2 === | ||
- | Массивы как в Паскале (только помним про регистрозависимость: все ключевые слова IN CAPITALS). <br> | ||
- | Пример объявления массива | ||
- | VAR | ||
- | a: ARRAY [-1..100] OF ARRAY [1..10] OF INTEGER; | ||
- | |||
- | Для передачи массива в качестве параметра (и только для этого) используется т.н. открытый (или гибкий) массив X: ARRAY OF T. Индексы будут отображены на 0..HIGH(X). | ||
- | |||
- | PROCEDURE SCAL(VAR x,y: ARRAY OF REAL): REAL; (* Зачем здесь VAR, не знаю. Должно быть можно без него. *) | ||
- | ============================================= | ||
- | VAR | ||
- | a: ARRAY [0..N - 1] OF REAL; | ||
- | b: ARRAY [1..N] OF REAL; | ||
- | ============================================= | ||
- | SCAL(a, b); | ||
- | |||
- | == Управление памятью == | ||
- | === Классы памяти === | ||
- | |||
- | '''Статическая''' | ||
- | Всё что связано со словом «статический» размещается в блоке статической памяти. Время жизни – от начала программы либо момента первого входа в блок, и до конца программы. | ||
- | |||
- | '''Квазистатическая''' | ||
- | Квазистатическая память связана с понятием блока: переменные связана с этим блоком (от момента объявления, точнее, прохода code flow через объявление, до выхода из блока). Размещаются в стеке. Еще автоматической называют (автоматическая переменная). | ||
- | |||
- | '''Динамическая''' | ||
- | Время жизни зависит от процедур (ручное управление памятью) или от сборщика мусора. | ||
=== Указатели === | === Указатели === | ||
- | Ада, C, C++, C#, Delphi, Оберон | + | Ада, C, C++, C#, Delphi, Оберон |
Указатели языка Ада 83 ссылаются только на объекты из | Указатели языка Ада 83 ссылаются только на объекты из | ||
Строка 307: | Строка 165: | ||
ТипУказатель = POINTER TO Тип. | ТипУказатель = POINTER TO Тип. | ||
Любая переменная-указатель может принимать значение NIL, которое не указывает ни на какую переменную вообще. | Любая переменная-указатель может принимать значение NIL, которое не указывает ни на какую переменную вообще. | ||
- | |||
- | В Modula-2 можно объявлять указатель на что угодно. При том как на переменные в динамической памяти, так и в статической. | ||
- | Есть адресная арифметика (ADDADR, SUBADR, DIFADR), преобразование типов указателей (CAST), разыменование (^), функция взятия адреса (ADR), аллокация и деаллокация (NEW-DISPOSE или ALLOCATE-DEALLOCATE - два варианта), размер типа в байтах (TSIZE) и NIL. В случае получения невалидного адреса, разыменования NIL и т.п. выдаётся ошибка. | ||
- | TYPE | ||
- | TreePtr = POINTER TO TreeGlue; | ||
- | TreeGlue = RECORD | ||
- | key : KeyType; | ||
- | left : TreePtr; (* left child *) | ||
- | right : TreePtr; (* right child *) | ||
- | END; | ||
В Java явных указателей нет. | В Java явных указателей нет. | ||
- | |||
- | == Преобразование типов == | ||
- | === Явное преобразование типов === | ||
- | Преобразование типов называется ''явным,'' если оно указано программистом в исходном коде. | ||
- | === Неявное преобразование типов === | ||
- | |||
- | Преобразование типов называется ''неявным'', если оно не указывается программистом, но, тем не менее, выполняется (в языках со статической типизацией — соответствующие конструкции подставляются на этапе компиляции). В языках '''C'''<ref>Если не считать (T *) → (void *).</ref>, '''C#''', '''Java''', '''Pascal''', '''Delphi''', '''Modula-2''', '''Оберон''', '''Оберон-2''' неявными могут быть только расширяющие преобразования (иначе говоря, преобразования, к более общему типу<ref>Следует иметь ввиду, что в случае простых типов не всегда более общий тип может отобразить менее общий. К примеру, вещественный тип single стандарта IEEE 754 не может точно представить число 16777217, в то время как 32-битный целочисленный тип может.</ref>); в '''С++''' — любые преобразования. В языке '''Ада''' неявных преобразований почти<ref>Исключение составляет, например, неявное приведение числового литерала к конкретному типу. Подробнее: [http://www.adaic.org/resources/add_content/standards/05rm/html/RM-4-6.html#I2822].</ref> нет. | ||
- | |||
- | ==== Неявное преобразование для пользовательских классов ==== | ||
- | |||
- | Язык Java запрещает любые неявные преобразования между объектами классов (исключение составляют только неявные преобразования к стандартному типу String, разрешенные в некоторых | ||
- | контекстах). | ||
- | |||
- | Языки C++ и C# разрешают неявные преобразования для классов, определяемых пользователем. | ||
- | |||
- | В '''C++''' преобразования определяются специальными функциями-членами: конструкторами преобразования и функциями преобразования. Конструктор преобразования имеет прототип вида: | ||
- | Х(Т) // или Х(Т&) или X (const Т&) | ||
- | |||
- | Функция преобразования имеет вид: | ||
- | class X { | ||
- | operator Т(); | ||
- | }; | ||
- | |||
- | В языке '''C#''' область применения пользовательских преобразований уже, чем в языке C++. Можно | ||
- | определять свои преобразования только между двумя классами, нельзя определять преобразования в типы значений или из них. Преобразование из класса X в класс Y реализуется с помощью специального метода — функции преобразования: | ||
- | static operator Y (X х) { ... } | ||
- | Функция преобразования может быть только статическим методом либо класса х, либо класса Y. Если такая функция преобразования есть, то она вызывается с использованием обычного синтаксиса преобразований: (Y) х. Компилятор вставляет неявное преобразование из X в Y только, если соответствующая функция преобразования снабжена модификатором implicit: | ||
- | static implicit operator Y (X x) { ... } | ||
- | |||
- | Если же используется модификатор explicit, то функция преобразования может вызываться только явно. По умолчанию принимается модификатор explicit, что снижает вероятность случайной | ||
- | ошибки. | ||
- | |||
- | В '''Delphi''' есть неявное преобразование типов, работает для функций. Пример (не работает для Writeln, потому что это не функция, а конструкция языка): | ||
- | |||
- | program Overloads; | ||
- | {$APPTYPE CONSOLE} | ||
- | type | ||
- | TRec = record | ||
- | private | ||
- | function GetOrd: Integer; | ||
- | public | ||
- | class operator Implicit(const Value: TRec): Integer; | ||
- | property ord: Integer read GetOrd; | ||
- | end; | ||
- | |||
- | class operator TRec.Implicit(const Value: TRec): Integer; | ||
- | begin | ||
- | Result := 0; | ||
- | end; | ||
- | |||
- | function TRec.GetOrd: Integer; | ||
- | begin | ||
- | Result := 0; | ||
- | end; | ||
- | |||
- | procedure Foo(i: Integer); | ||
- | begin | ||
- | end; | ||
- | |||
- | var | ||
- | R: TRec; | ||
- | a: array[0..0] of Integer; | ||
- | |||
- | begin | ||
- | Writeln(R);//E2054 Illegal type in Write/Writeln statement | ||
- | Writeln(Integer(R));//explicit cast, provided by class operator Implicit | ||
- | Writeln(R.ord);//my preferred option, a property | ||
- | a[R] := 0;//E2010 Incompatible types: 'Integer' and 'TRec' | ||
- | a[Integer(R)] := 0;//again, explicit cast is fine | ||
- | a[R.ord] := 0;//or using a property | ||
- | Foo(R);//implicit cast used for actual parameters | ||
- | end. | ||
- | |||
- | === Понятия ''conversion'' и ''casting'' === | ||
- | В большинстве языков, основанных на базе '''Algol''' и обладающих механизмом вложенных функций - например, в '''Ada, Delphi, Modula 2''' и '''Pascal,''' понятия ''conversion'' и ''casting'' принципиально различны. Понятие ''conversion'' относится к явному или неявному изменению значения одного типа данных на значение другого типа данных (например, расширение 16-битного целого до 32-битного). В этом случае, могут измениться требования к объёму выделенной памяти; могут возникнуть потери точности или округления. Понятие ''casting,'' напротив, обозначает ''явное'' изменение интерпретации ''последовательности бит.'' Например, последовательность из 32 бит может быть интерпретирована как целое без знака, как массив из 32 значений типа boolean или как вещественное число c одинарной точностью, соответствующее стандарту IEEE. | ||
- | В '''C-подобных''' языках, понятием ''casting'' обозначается явное приведение типа в независимости от того, является ли оно изменением интерпретации последовательности бит, либо же настоящим преобразованием типа. | ||
- | === Упаковка и распаковка === | ||
- | Данные понятия определены для языков '''C#''' и '''Java.''' | ||
- | : ''Упаковкой (boxing)'' называется процесс преобразования значения простого типа значения в экземпляр соответствующего класса-оболочки. | ||
- | : ''Распаковкой (unboxing)'' называется, очевидно, процесс преобразования экземпляра класса-оболочки в значение соответствующего простого типа. | ||
- | |||
- | ==== C# ==== | ||
- | В '''C#''' упаковка и распаковка выполняются автоматически. | ||
- | |||
- | Пример упаковки и распаковки: | ||
- | int i = 123; | ||
- | // The following line boxes i. | ||
- | object o = i; | ||
- | |||
- | o = 123; | ||
- | i = (int) o; // unboxing | ||
- | |||
- | ==== Java ==== | ||
- | В '''Java''' автоупаковка и автораспаковка поддерживаются начиная с J2SE 5.0 (сентябрь 2004 года). | ||
- | |||
- | Пример упаковки и распаковки: | ||
- | int i = 123; | ||
- | Integer boxedI = Integer.valueOf(i); // boxing | ||
- | |||
- | Integer boxedI = Integer.valueOf(123); | ||
- | int i = boxedI.intValue(); // unboxing | ||
- | |||
- | ==== Другие языки ==== | ||
- | |||
- | В некоторых языках упаковка и распаковка отсутствуют. Например, в '''Smalltalk''' любое значение принадлежит некоторому классу (т.е. даже значения простых типов являются экземплярами классов). | ||
- | |||
- | В JavaScript ситуация несколько иная. Например, есть примитивный тип ''Number'' для чисел. В отличие от Java и C#, это тип является полноценным (к объектам этого типа можно применить операцию <code>typeof</code>). Однако при вызове методов примитивный тип упаковывается в объект, прототипом которого является <code>Number.prototype</code> (это не тот же самый ''Number''-примитивный тип!), и в котором уже определены нужные методы. Пример кода, который это демонстрирует: | ||
- | <pre> | ||
- | Number.prototype.test = function() { return this; } | ||
- | var x = 5; | ||
- | alert(x + " " + typeof x); | ||
- | x = x.test(); | ||
- | alert(x + " " + typeof x); | ||
- | </pre> | ||
== Операторный базис языков программирования. Управление последовательностью вычислений == | == Операторный базис языков программирования. Управление последовательностью вычислений == | ||
=== ADA === | === ADA === | ||
- | + | Джентльменский набор: | |
+ | |||
'''if''' condition '''then''' | '''if''' condition '''then''' | ||
statement; | statement; | ||
Строка 492: | Строка 227: | ||
Do_Something (I) | Do_Something (I) | ||
'''end''' '''loop''' For_Loop; | '''end''' '''loop''' For_Loop; | ||
- | |||
- | ''(Замечание: именовать циклы необязательно.)'' | ||
=== ОБЕРОН И ОБЕРОН-2 === | === ОБЕРОН И ОБЕРОН-2 === | ||
- | + | ОператорIf = | |
- | + | ||
- | + | ||
IF Выражение THEN ПоследовательностьОператоров | IF Выражение THEN ПоследовательностьОператоров | ||
{ELSIF Выражение THEN ПоследовательностьОператоров} | {ELSIF Выражение THEN ПоследовательностьОператоров} | ||
Строка 505: | Строка 236: | ||
CASE ch OF | CASE ch OF | ||
- | "A" .. "Z": ReadIdentifier | + | "A" .. "Z": ReadIdentifier |
- | "0" .. "9": ReadNumber | + | | "0" .. "9": ReadNumber |
- | "'", '"': ReadString | + | | "'", '"' : ReadString |
ELSE SpecialCharacter | ELSE SpecialCharacter | ||
- | END | + | END |
WHILE Выражение DO | WHILE Выражение DO | ||
Строка 519: | Строка 250: | ||
UNTIL Выражение. | UNTIL Выражение. | ||
- | FOR v := | + | FOR v := beg TO end BY step DO statements END (В Оберон-2) |
- | + | ||
- | + | ||
- | + | ||
- | LOOP | + | LOOP ПоследовательностьОператоров END. |
- | + | ||
- | + | ||
- | + | ||
- | WITH | + | WITH v: T1 DO S1 | v: T2 DO S2 ELSE S3 END (В Оберон-2) |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Процедурные абстракции == | == Процедурные абстракции == | ||
- | |||
- | === Передача параметров в подпрограммы === | ||
- | |||
- | Для каждой подпрограммы указывается набор формальных параметров. Можно рассматривать формальные параметры как локальные переменные тела подпрограммы. При вызове подпрограммы указывается список фактических параметров. Соответствие между фактическими и формальными параметрами выполняется по позиции в списке: первый фактический параметр соответствует первому формальному параметру и т. д. Такой способ называется ''позиционным''. Язык С#, начиная с версии 4, предусматривает альтернативный — ''ключевой'' способ отождествления, в котором используются имена формальных параметров, но мы не будем его рассматривать. Существует три вида формальных параметров: | ||
- | * входные параметры (параметры, от которых требуется только значение). Мы используем только значения фактических параметров, которые не меняются при выходе из тела функции; | ||
- | * выходные параметры (эти параметры не обязаны иметь начальное значение, но могут быть изменены в теле функции); | ||
- | * изменяемые параметры (требуется и исходное значение, и возможность его изменения). | ||
- | |||
- | С входным параметром может связываться произвольное выражение, а выходным или изменяемым — только объекты, которые могут стоять в левой части оператора присваивания. В большинстве языков программирования вместо указания вида параметра указывается способ (механизм) связывания параметра, называемый способом передачи параметра. | ||
- | |||
- | Существует два основных способа передачи параметров: ''по значению'' и ''по ссылке''. | ||
- | |||
- | ==== Передача параметров по значению ==== | ||
- | |||
- | Формальный параметр есть некоторая локальная переменная. Место для локальных переменных отводится в стеке. При вызове подпрограммы значение фактического параметра копируется в соответствующий формальный параметр. Все изменения формального параметра связаны с изменением локальной переменной и не сказываются на фактическом параметре. Перед копированием может потребоваться приведение типа, если типы фактического и формального параметров не совпадают. | ||
- | |||
- | ==== Передача параметров по ссылке ==== | ||
- | |||
- | Фактически этот способ есть передача ссылки по значению. Формальный параметр — это ссылка на объект. (Существует мнение, что данное «определение» не только не отражает сути явления, но и неверно в корне. В дискуссии вокруг передачи аргументов в Java Dale King [http://www.yoda.arachsys.com/java/passing.html дал] следующее определение. ''Передача по ссылке — это когда lvalue формального параметра устанавливается в lvalue фактического параметра.'') В момент вызова происходит инициализация ссылки фактическим параметром. Преобразования типов в этот момент не происходит: типы формального и фактического параметров должны совпадать. Поскольку ссылка после инициализации отождествляется с объектом, то любые изменения формального параметра подразумевают изменения фактического параметра. Очевидно, что способ передачи по значению соответствует семантике входных формальных параметров. По ссылке можно передавать выходные и изменяемые параметры. | ||
- | |||
- | ==== Аргументы в C/C++ всегда передаются по значению ==== | ||
- | |||
- | В C++ есть ссылочный тип. Переменная ссылочного типа может ссылаться на значение любого типа, должна быть инициализирована и не может менять значения. С помощью передачи переменной ссылочного типа можно имитировать все возможности контрукции var из '''Pascal'''. Но можно действовать в стиле C — передавать указатель. В свою очередь, чтобы менять указатель, можно передавать в функцию/метод указатель или ссылку на него. | ||
- | |||
- | ==== Аргументы в Java всегда передаются по значению ==== | ||
- | |||
- | Существует распространённое '''заблуждение''' о том, что «объекты передаются по ссылке, а примитивные типы — по значению». | ||
- | '''На самом деле''' ситуация иная: | ||
- | # Аргументы любого типа передаются по значению. Объекты, однако, не передаются вообще. | ||
- | # Значения переменных всегда примитивы или ссылки (или null), но никак не объекты. | ||
- | Подробнее см. http://www.yoda.arachsys.com/java/passing.html . | ||
- | |||
- | В соответствии с изложенным выше, метод может изменить объект через аргумент-ссылку. С примитивным типом это не пройдёт, так как в Java нет ссылок на значения примитивных типов. Чтобы иметь возможность изменить из метода значение некоторой внешней переменной примитивного типа, нужно чтобы эта переменная была полем некоторого объекта. | ||
- | |||
- | В связи с этим для примитивных типов были введены классы-обёртки. Объект такого класса содержит в себе значение примитивного типа, которое можно как прочитать, так и поменять. См. также [[Сравнение_Языков_Программирования#.D0.A3.D0.BF.D0.B0.D0.BA.D0.BE.D0.B2.D0.BA.D0.B0_.D0.B8_.D1.80.D0.B0.D1.81.D0.BF.D0.B0.D0.BA.D0.BE.D0.B2.D0.BA.D0.B0|Упаковка и распаковка]] | ||
=== Перегрузка операций === | === Перегрузка операций === | ||
Ада 83, Ада 95, Си++, Java, Delphi, C# | Ада 83, Ада 95, Си++, Java, Delphi, C# | ||
- | Понятие «перегрузка» | + | Понятие «перегрузка» означает, что одному имени в одной области |
- | + | видимости может соответствовать несколько определений. В современных | |
- | Пример на языке | + | языках программирования перегружаться могут только имена подпрограмм, |
+ | но не типов, переменных, модулей. | ||
+ | Пример на языке Си++: | ||
class X { | class X { | ||
public: | public: | ||
void f(); | void f(); | ||
- | void f(int) | + | void f (int) |
}; | }; | ||
Строка 763: | Строка 276: | ||
a.f(0); // вторая функция | a.f(0); // вторая функция | ||
- | Отличие перегрузки от замещения | + | Отличие перегрузки от замещения состоит во-первых, в том, что |
+ | перегрузка обрабатывается статически (на этапе трансляции), в во-вторых, | ||
+ | при замещении речь идет о разных областях видимости: базовый класс с | ||
+ | объявлением виртуального метода (объемлющая область видимости) и | ||
+ | производный класс с замещающим методом (вложенная область видимости). | ||
=== ADA === | === ADA === | ||
Строка 780: | Строка 297: | ||
=== ОБЕРОН И ОБЕРОН-2 === | === ОБЕРОН И ОБЕРОН-2 === | ||
Имеются два вида процедур: собственно процедуры и процедуры- функции. Последние активизируются обозначением функции как часть выражения и возвращают результат, который является операндом выражения. Собственно процедуры активизируются вызовом процедуры. Процедура является процедурой-функцией, если ее формальные параметры задают тип результата. Тело процедуры-функции должно содержать оператор возврата, который определяет результат. | Имеются два вида процедур: собственно процедуры и процедуры- функции. Последние активизируются обозначением функции как часть выражения и возвращают результат, который является операндом выражения. Собственно процедуры активизируются вызовом процедуры. Процедура является процедурой-функцией, если ее формальные параметры задают тип результата. Тело процедуры-функции должно содержать оператор возврата, который определяет результат. | ||
- | |||
- | PROCEDURE log2 (x: INTEGER): INTEGER; | ||
- | VAR y: INTEGER; (*предполагается x>0*) | ||
- | BEGIN | ||
- | y := 0; WHILE x > 1 DO x := x DIV 2; INC(y) END; | ||
- | RETURN y | ||
- | END log2 | ||
== Определение новых типов данных. Логические модули. Классы == | == Определение новых типов данных. Логические модули. Классы == | ||
Строка 861: | Строка 371: | ||
При подключении потомка родитель-пакет подключается автоматически. | При подключении потомка родитель-пакет подключается автоматически. | ||
- | + | О подключениях. Подключить пакет можно с помощью конструкции '''with'''. | |
'''with''' Points.RandomDistributions; | '''with''' Points.RandomDistributions; | ||
После этого можно будет пользоваться ввсем, что в пакете лежит, через точечную нотацию. Если же вызовов слишком много, то можно влить содержимое пакета в текущую область видимости с помощью '''use''' (только после подключения!). | После этого можно будет пользоваться ввсем, что в пакете лежит, через точечную нотацию. Если же вызовов слишком много, то можно влить содержимое пакета в текущую область видимости с помощью '''use''' (только после подключения!). | ||
Строка 880: | Строка 390: | ||
является (прямым) расширением типа T, и наоборот, T называется (прямым) базовым (base) типом для T’. | является (прямым) расширением типа T, и наоборот, T называется (прямым) базовым (base) типом для T’. | ||
- | == | + | == Инкапсуляция и абстрактные типы данных == |
- | === | + | ===ОБЕРОН И ОБЕРОН-2=== |
- | + | Позволяют открывать поля структуры | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | === | + | === ADA === |
- | + | Наследование в Аде происходит путем создания нового пакета и расширения в нем базовой записи: | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | '''package''' Person '''is''' | |
+ | '''type''' Object '''is''' '''tagged''' '''private'''; | ||
+ | '''procedure''' Put (O : Object); | ||
+ | '''private''' | ||
+ | '''type''' Object '''is''' | ||
+ | '''record''' | ||
+ | Name : String (1 .. 10); | ||
+ | Gender : Gender_Type; | ||
+ | '''end record'''; | ||
+ | '''end Person'''; | ||
- | + | '''with''' Person; | |
- | + | '''package''' Programmer '''is''' | |
- | + | '''type''' Object '''is new''' Person.Object '''with private'''; | |
- | + | '''private''' | |
- | + | '''type''' Object '''is''' | |
- | + | '''record''' | |
- | + | abuility : Language_List; | |
- | + | '''end record'''; | |
- | + | '''end Person'''; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | '' | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ООП в Аде является вполне полноценным c Динамическим полиморфизмом, RTTI, абстрактными типами и интерфейсами. | |
== Модульность и раздельная трансляция == | == Модульность и раздельная трансляция == | ||
Строка 1106: | Строка 433: | ||
=== Модульность === | === Модульность === | ||
- | + | ===ОБЕРОН И ОБЕРОН-2=== | |
:Модуль - совокупность объявлений констант, типов, переменных и процедур вместе с последовательностью операторов, предназначенных для присваивания начальных значений переменным. Модуль представляет собой текст, который является единицей компиляции. | :Модуль - совокупность объявлений констант, типов, переменных и процедур вместе с последовательностью операторов, предназначенных для присваивания начальных значений переменным. Модуль представляет собой текст, который является единицей компиляции. | ||
Строка 1163: | Строка 490: | ||
Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. | Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. | ||
Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон. | Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон. | ||
- | |||
- | ==== Modula-2 ==== | ||
- | Программа представляет собой набор модулей — самостоятельных единиц компиляции, которые могут компилироваться раздельно. При этом программный модуль может быть (но не обязан) разделён на две части: модуль определений и модуль реализации. Модуль определений — это внешний интерфейс модуля, то есть набор экспортируемых им имён констант, переменных, типов, заголовков процедур и функций, которые доступны внешним модулям. Модуль реализации содержит программный код, в частности, конкретизацию описаний всего, что перечислено в модуле определений. Например, некоторый тип «запись» может быть объявлен в модуле определений с указанием лишь его имени, а в модуле реализации — с полной структурой. В этом случае внешние модули могут создавать значения данного типа, вызывать процедуры и функции, работающие с ним, выполнять присваивание переменных, но не имеют прямого доступа к структуре значений, поскольку эта структура не описана в модуле определений. Если для этого же типа описать в модуле определений структуру, то она станет доступна. Помимо модулей глобального уровня в Модуле-2 допускается создавать локальные модули. <br> | ||
- | Импорт определений, описанных в прочих модулях, полностью контролируется. Можно импортировать модули определений целиком, но синтаксис позволяет существенно уточнять списки импорта, например, импортировать из модуля конкретные константы, переменные, процедуры и функции, только те, которые необходимы. | ||
- | |||
- | DEFINITION MODULE ModuleName; (* Модуль определений *) | ||
- | {Import} | ||
- | {Declaration} | ||
- | END ModuleName. | ||
- | ======================== | ||
- | Где Import это: | ||
- | [FROM ModuleName] IMPORT | ||
- | identifier {,identifier}; | ||
- | |||
- | IMPLEMENTATION MODULE ModName; (* Модуль реализаций *) | ||
- | {Import} | ||
- | {Declaration} | ||
- | [ BEGIN | ||
- | ListOfStatements | ||
- | [EXCEPT | ||
- | ListOfStatements] | ||
- | [ | ||
- | FINALLY | ||
- | ListOfStatements | ||
- | EXCEPT | ||
- | ListOfStatements | ||
- | ] | ||
- | ] | ||
- | END ModName. | ||
- | |||
- | MODULE ModName; (* Должен существовать единственный на весь проект. Это main. *) | ||
- | {Import} | ||
- | {Declaration} | ||
- | BEGIN | ||
- | ListOfStatements | ||
- | [EXCEPT | ||
- | ListOfStatements] | ||
- | END ModName. | ||
- | |||
- | Для обеспечения видимости в других модулях объявления функций, переменных и типов, описанные в модулях определений, можно импортировать. Остановимся на типах. При импортировании их внутренняя структура становится видна импортирующему модулю (т.н. прозрачный экспорт). Существует скрытый экспорт (opaque export), где видно становится только имя типа. Он возможен только для указательного типа (но сделаем указатель на структуру - и вуаля, получим инкапсуляцию и абстракцию данных). | ||
- | |||
- | === ADA === | ||
- | Ада, наверное - единственный язык со вложенностью модулей, их раздельной компиляцией и двойной связью одновременно. | ||
- | Опишем вложенную спецификацию, тут ничего сложного: | ||
- | |||
- | '''package''' Outer '''is''' | ||
- | '''...''' | ||
- | '''procedure''' some_proc (X: Some_type) '''is private;''' | ||
- | '''package''' Inner '''is''' | ||
- | '''...''' ''-- Тут, в общем то видно все, что есть в пакете Outer. | ||
- | '''end''' Inner; | ||
- | '''...''' | ||
- | '''end''' Outer; | ||
- | |||
- | Тела этих пакетов, как и тело функции, можно разнести по разным файлам (единицам компиляции), используя "заглушку" '''separate''': | ||
- | |||
- | '''package''' '''body''' Outer '''is''' | ||
- | '''...''' | ||
- | '''package''' Inner '''is''' '''separate'''; | ||
- | '''...''' | ||
- | '''procedure''' some_proc (X: some_type) '''is''' '''separate'''; | ||
- | '''end''' Outer; | ||
- | |||
- | Теперь опишем тела модуля Inner и процедуры. | ||
- | |||
- | '''separate''' (Outer) ''--Тут нет `;' '' | ||
- | '''package''' '''body''' Inner '''is''' | ||
- | '''...''' | ||
- | '''end''' Inner; | ||
- | |||
- | '''separate''' (Outer) | ||
- | '''procedure''' some_proc (X: some_type) '''is''' | ||
- | '''...''' | ||
- | '''end''' some_proc; | ||
- | |||
- | Вот здесь заглушка '''separate''' и является двойной модульной связью. | ||
== Исключительные ситуации и обработка ошибок == | == Исключительные ситуации и обработка ошибок == | ||
- | |||
- | ; Зачечание | ||
- | : Кроме перечисленных в итоговой таблице языков исключения поддерживает Visual Basic. | ||
=== Исключения и блоки try {} catch {} finally {}. Семантика возобновления и семантика завершения. === | === Исключения и блоки try {} catch {} finally {}. Семантика возобновления и семантика завершения. === | ||
Строка 1252: | Строка 500: | ||
того же блока). | того же блока). | ||
Пример языка c семантикой возобновления: Visual Basic. | Пример языка c семантикой возобновления: Visual Basic. | ||
- | |||
- | Моделирование семантики возобновления на C++: | ||
- | bool need_restart = true; | ||
- | while (need_restart) { | ||
- | need_restart = false; | ||
- | try { | ||
- | // Some code here | ||
- | } catch (...) { | ||
- | // C# - просто catch, без круглых скобок | ||
- | // Java - catch (Throwable e) | ||
- | |||
- | need_restart = true; | ||
- | } | ||
- | } | ||
'''Семантика завершения''': после возникновения исключения блок, в | '''Семантика завершения''': после возникновения исключения блок, в | ||
Строка 1274: | Строка 508: | ||
'''catch''' (в delphi - '''except''') - то что будет выполнено в случае ошибки в блоке try. | '''catch''' (в delphi - '''except''') - то что будет выполнено в случае ошибки в блоке try. | ||
'''finally''' - то что будет выполнено в любом случае, вне зависимости от того что произошло в блоке try. | '''finally''' - то что будет выполнено в любом случае, вне зависимости от того что произошло в блоке try. | ||
- | |||
- | Конструкция '''try''' ... '''finally''' ... есть в C#, Java, Delphi. Декларируется, что в C++ в '''finally''' нет необходимости в виду RAII и, как следствие, выполнении деструкторов на выходе из блока. | ||
- | |||
- | === throw (C++) и throws (Java) === | ||
- | |||
- | Текст раздела построен с т.з. программиста Java (иначе говоря, обозначены отличия синтаксиса и семантики конструкции C++ от конструкции Java, а не наоборот). Причина — одно из заданий экзамена по ЯПам звучит примерно как «опишите конструкцию throws в Java (зачем нужно и как работает). Как моделируется на C++, Delphi<ref>Видимо, без использования «родных» аналогичных конструкций, нужно уточнить.</ref>?». | ||
- | |||
- | Примеры употребления конструкций: | ||
- | |||
- | // Java | ||
- | |||
- | void someMethod() throws IOException, SomeOtherException { … } | ||
- | // IOException — стандартный класс исключения, наследник Exception. | ||
- | // SomeException должен быть наследником Throwable. | ||
- | |||
- | void someMethod() { … } | ||
- | // Запись «не выбрасывает исключения»: отсутствие throws и списка исключений. | ||
- | |||
- | // C++ | ||
- | |||
- | void someMethod() throw (SomeException1, SomeException2) { … } | ||
- | // SomeException1, SomeException2 — вообще говоря, любые типы. | ||
- | // Декларациии throw должны совпадать как при определении, так и при описании. | ||
- | |||
- | void someMethod() throw () { … } | ||
- | // Запись «не выбрасывает исключения»: throw (). | ||
- | |||
- | void someMethod() { … } | ||
- | // Может выбрасывать любые исключения. | ||
- | |||
- | Данные конструкции служат для того, чтобы показать программисту и компилятору, что данный метод (или, в случае C++, метод или функция) может выбрасывать исключения соответствующих типов. Насколько [[Участник:Totktonada|я]] понимаю, всё это влияет только на статические проверки компилятора и эстетические чувства программиста. В runtime эти декларации никак себя не проявляют, поэтому употребляемые здесь «может / не может выбрасывать исключение данного типа» и тому подобные обороты следует понимать в контексте статических проверок. ''(Замечание: не совсем верно. Исключения могут возникнуть в виртуальной функции или в отдельно оттранслированной. Memento std::unexpected().)'' | ||
- | |||
- | В Java считается, что метод, выбрасывающий исключение должен обозначить это с помощью конструкции throws. Иначе говоря, считается, что если директивы throws нет, то метод не выбрасывает исключений. Компилятор делает некоторые статические проверки, по крайней мере, запрещает выбрасывать исключения, не перечисленные в throws, явно — с помощью оператора throw. | ||
- | |||
- | В C++, в отличие от Java, если директива throw не задана, то считается, что данный метод или функция может выбрасывать любые исключения. Статические (времени компиляции) проверки делаются только для тех методов/функций, для которых указан (возможно пустой) список исключений. | ||
- | |||
- | === Одно из заданий экзамена по ЯПам === | ||
- | |||
- | 2004 г, задание 8. Смоделируйте на языке Си++ функцию | ||
- | void f() throw (E1,E2,E3) { g(); h(); } | ||
- | предполагая, что конструкция throw<ref>Видимо, подразумевается конструкция throw (…) в заголовке метода/функции, а не выбрасывание (или повторное выбрасывание) исключения с помощью оператора throw.</ref> не допускается компилятором. | ||
- | |||
- | void f() | ||
- | { | ||
- | try { | ||
- | g(); h(); | ||
- | } catch (E1) { | ||
- | throw; | ||
- | } catch (E2) { | ||
- | throw; | ||
- | } catch (E3) { | ||
- | throw; | ||
- | } catch (...) { | ||
- | unexpected(); | ||
- | } | ||
- | } | ||
=== ADA === | === ADA === | ||
- | |||
Создание исключения: | Создание исключения: | ||
New_Exception: '''exception'''; | New_Exception: '''exception'''; | ||
- | + | Выбрасывание исключения: | |
'''raise''' New_Exception; | '''raise''' New_Exception; | ||
Строка 1349: | Строка 526: | ||
Do_Smth; | Do_Smth; | ||
'''end'''; | '''end'''; | ||
+ | |||
+ | '''finally-блока в Аде таки нету.''' Однако он [http://stackoverflow.com/questions/4804135/best-practice-for-implementing-in-ada-2005-or-2012-an-equivalent-of-the-java-f имитируется]. | ||
Отлов исключения так же может иметь такой вид: | Отлов исключения так же может иметь такой вид: | ||
Строка 1357: | Строка 536: | ||
== Наследование типов и классов == | == Наследование типов и классов == | ||
- | |||
- | === C# и Java === | ||
- | |||
- | В C# и Java можно в дочернем классе сослаться на экземпляр родительского с помощью ключевых слов '''base''' (C#) и '''super''' (Java). | ||
- | |||
- | Кроме того, в этих языках есть ключевые слова '''sealed''' (C#) и '''final''' (Java). Они могут находиться в заголовке<ref>Вероятно, только перед определением типа.</ref> метода (в случае C# — только виртуального) или класса ('''final''' также может находиться в описании поля, но это «другая песня»). | ||
- | |||
- | В C# '''sealed''' в заголовке виртуального метода означает запрет перегрузки (англ. override) метода в производных классах. В заголовке класса — запрет наследования от данного класса. | ||
- | |||
- | В Java '''final''' в заголовке метода означает, запрет замещения (скрытия, англ. hide) или перегрузки (англ. override) метода в производных классах. В заголовке класса — запрет наследования от данного класса. | ||
- | |||
- | === ADA === | ||
- | Наследование в Аде происходит путем создания нового пакета и расширения в нем базовой записи: | ||
- | |||
- | '''package''' Person '''is''' | ||
- | '''type''' Object '''is''' '''tagged''' '''private'''; | ||
- | '''procedure''' Put (O : Object); | ||
- | '''private''' | ||
- | '''type''' Object '''is''' | ||
- | '''record''' | ||
- | Name : String (1 .. 10); | ||
- | Gender : Gender_Type; | ||
- | '''end record'''; | ||
- | '''end Person'''; | ||
- | |||
- | '''with''' Person; | ||
- | '''package''' Programmer '''is''' | ||
- | '''type''' Object '''is new''' Person.Object '''with private'''; | ||
- | '''private''' | ||
- | '''type''' Object '''is''' | ||
- | '''record''' | ||
- | abuility : Language_List; | ||
- | '''end record'''; | ||
- | '''end Person'''; | ||
- | |||
- | ООП в Аде является вполне полноценным c Динамическим полиморфизмом, [http://esyr.org/wiki/%D0%A1%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%AF%D0%B7%D1%8B%D0%BA%D0%BE%D0%B2_%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F#ADA_8 RTTI], абстрактными типами и интерфейсами. | ||
== Динамический полиморфизм == | == Динамический полиморфизм == | ||
- | + | == Абстрактные классы и интерфейсы == | |
- | + | Абстрактный тип данных (АТД) — это тип с полностью | |
+ | инкапсулированной структурой. Использовать объекты АТД возможно | ||
+ | только при помощи явно определенных в интерфейсе типа операций. | ||
+ | Абстрактный класс (АК) — это класс, содержащий хотя бы один | ||
+ | абстрактный метод. | ||
- | + | Прямой связи между АК и АТД нет. АТД может быть абстрактным | |
- | + | классом, а может и не быть. Аналогично, АК может иметь | |
- | + | инкапсулированную структуру, а может и не иметь. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | Прямой связи между АК и АТД нет. АТД может быть абстрактным классом, а может и не быть. Аналогично, АК может иметь инкапсулированную структуру, а может и не иметь. | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Множественное наследование == | == Множественное наследование == | ||
- | Полностью реализовано только в C++. В | + | Полностью реализовано только в C++. В Java и C# множественное наследование поддерживается только для интерфейсов. |
== Динамическая идентификация типа == | == Динамическая идентификация типа == | ||
- | |||
- | Динамическая идентификация типа данных (Run-time type identification, RTTI) — механизм, который позволяет определить тип данных переменной или объекта во время выполнения программы. | ||
- | |||
- | === C++ === | ||
- | В C++ для динамической идентификации типов применяются операторы dynamic_cast и typeid (определён в файле typeinfo.h), для использования которых информацию о типах во время выполнения обычно необходимо добавить через опции компилятора при компиляции модуля. | ||
- | |||
- | Оператор dynamic_cast пытается выполнить приведение к указанному типу с проверкой. Целевой тип операции должен быть типом указателя, ссылки или void*. | ||
- | |||
- | Оператор typeid возвращает ссылку на структуру type_info, которая содержит поля, позволяющие получить информацию о типе. | ||
- | |||
- | === Delphi === | ||
- | |||
- | Компилятор Delphi сохраняет в исполняемом файле программы информацию обо всех классах, используемых в ней. При создании любого объекта в памяти перед ним располагается заголовок, в котором есть в том числе ссылка на структуру-описатель класса этого объекта. Встроенные в язык функции работают с этой информацией прозрачно для программиста. Оператор is позволяет проверить, является ли объект или тип наследником определённого типа, а оператор as является аналогом dynamic_cast в C++. | ||
- | |||
- | === C# === | ||
- | |||
- | В C# для определения типа объекта во время исполнения используется метод GetType, а также ключевые слова is и as, которые являются аналогами для typeid и dynamic_cast в C++ соответственно. | ||
- | |||
- | === Оберон-2 === | ||
- | |||
- | В Оберон-2 есть два средства для идентификации типа: операция IS и охрана типа. | ||
- | |||
- | ==== Проверка типа ==== | ||
- | v IS T означает "динамический тип v есть T (или расширение T)" и называется проверкой типа. | ||
- | Проверка типа применима, если | ||
- | |||
- | 1. v - параметр-переменная типа запись, или v - указатель, и если | ||
- | |||
- | 2. T - расширение статического типа v | ||
- | |||
- | ==== Охрана типа ==== | ||
- | Операторы with выполняют последовательность операторов в зависимости от | ||
- | результата проверки типа и применяют охрану типа к каждому вхождению | ||
- | проверяемой переменной внутри этой последовательности операторов. | ||
- | Если v - параметр-переменная типа запись или переменная-указатель, и если ее статический тип T0, оператор | ||
- | |||
- | WITH v: T1 DO S1 | v: T2 DO S2 ELSE S3 END | ||
- | |||
- | имеет следующий смысл: если динамический тип v - T1, то выполняется | ||
- | последовательность операторов S1 в которой v воспринимается так, будто она | ||
- | имеет статический тип T1; иначе, если динамический тип v - T2, выполняется | ||
- | S2, где v воспринимается как имеющая статический тип T2; иначе выполняется | ||
- | S3. T1 и T2 должны быть расширениями T0. Если ни одна проверка типа не | ||
- | удовлетворена, а ELSE отсутствует, программа прерывается. | ||
- | |||
- | === Java === | ||
- | |||
- | В Java тип объекта может быть получен при помощи метода getClass(), объявленного в классе java.lang.Object и потому реализуемого каждым классом. Для проверки принадлежности объекта определенному типу используется оператор instanceof (obj instanceof SomeClass), он заменяет dynamic_cast из C++. Также принадлежность объекта классу может быть определена с помощью оператора приведения типа, который в случае несоответствия типов выбрасывает исключение ClassCastException. | ||
- | |||
- | === ADA === | ||
- | В Аде для определения типа существует ключевое слово '''in''' работающее аналогично '''is''' в, скажем, Oberon-2. | ||
- | После этого можно приводить типы, пользуясь мощным механизм конвертирования Ады (в аде вместо понятия приведения типов/type casting используется понятие конвертирование типов/type conversion): | ||
- | Derived_Object: Derived := Derived (Base_Object) ''-- Здесь будет производится проверка в run-time'' | ||
== Понятие о родовых объектах. Обобщенное программирование == | == Понятие о родовых объектах. Обобщенное программирование == | ||
=== ADA === | === ADA === | ||
- | Note to C++ programmers: generic units are similar to C++ templates. | + | Note to C++ programmers: generic units are similar to C++ templates. [http://www.example.com Ada Programming] |
Объявляем шаблон: | Объявляем шаблон: | ||
Строка 1698: | Строка 584: | ||
:Операторы with выполняют последовательность операторов в зависимости от результата проверки типа и применяют охрану типа к каждому вхождению проверяемой переменной внутри этой последовательности операторов. | :Операторы with выполняют последовательность операторов в зависимости от результата проверки типа и применяют охрану типа к каждому вхождению проверяемой переменной внутри этой последовательности операторов. | ||
- | == | + | == Пример кода на Java == |
- | + | package MyPackage; | |
- | + | import java.lang.*; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | public class MyClass | |
- | + | { | |
- | + | public static void main(String [] argv) | |
- | + | { | |
- | + | int N = 5; | |
- | + | int M = 3; | |
- | + | double a[][] = new double[N][M]; // вместо указателей на массив - ссылки | |
- | + | double [][]b = new double[N][M]; | |
- | + | for (int i = 0; i < a.length; ++i) { // length - свойство массива (property) | |
- | + | for (int j = 0; j < a[i].length; ++j) { | |
- | + | a[i][j] = i * j; | |
- | + | } | |
+ | } | ||
+ | for (int i = 0; i < b.length; ++i) { | ||
+ | for (int j = 0; j < b[i].length; ++j) { | ||
+ | b[i][j] = i + j; | ||
+ | } | ||
+ | } | ||
+ | double res[][] = sumMatrices(a, b); | ||
+ | for (int i = 0; res != null && i < res.length; ++i) { | ||
+ | for (int j = 0; res[i] != null && j < res[i].length; ++j) { | ||
+ | System.out.print(res[i][j] + " "); | ||
+ | } | ||
+ | System.out.println(); | ||
+ | } | ||
+ | } | ||
+ | public static double[][] sumMatrices(double a[][], double b[][]) | ||
+ | { | ||
+ | label1: if (a != null && b != null && a.length == b.length) { | ||
+ | label2: { | ||
+ | for (double x[] : a) { // аналог for-each | ||
+ | for (double y[] : b) { | ||
+ | if (x.length != y.length) { | ||
+ | break label2; // аналог goto | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | break label1; | ||
+ | } | ||
+ | System.out.println("Bad Arrays..."); | ||
+ | return null; | ||
+ | } else { | ||
+ | System.out.println("Bad Arrays..."); | ||
+ | return null; | ||
+ | } | ||
+ | double [][]res = new double[a.length][a[0].length]; | ||
+ | for (int i = 0; i < a.length; ++i) { | ||
+ | for (int j = 0; j < a[i].length; ++j) { | ||
+ | res[i][j] = a[i][j] + b[i][j]; | ||
+ | } | ||
+ | } | ||
+ | return res; | ||
+ | } | ||
+ | } | ||
- | + | Вывод: | |
- | + | 0.0 1.0 2.0 | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | 1.0 3.0 5.0 | |
- | + | 2.0 5.0 8.0 | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | 3.0 7.0 11.0 | |
- | + | 4.0 9.0 14.0 | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Итоговая таблица == | == Итоговая таблица == | ||
Строка 2452: | Строка 660: | ||
{| border="1" | {| border="1" | ||
! | ! | ||
- | ! | + | !C |
- | !C++ | + | !C++ |
!C# | !C# | ||
!Java | !Java | ||
Строка 2464: | Строка 672: | ||
!Ada95 | !Ada95 | ||
|- | |- | ||
- | ! | + | !есть оператор перехода «goto метка» |
|есть | |есть | ||
|есть | |есть | ||
|есть | |есть | ||
- | |нет<ref>Есть break | + | |нет<ref>Есть break ''label'', где ''label'' ставится с двоеточием перед началом цикла.</ref> |
|есть | |есть | ||
|есть | |есть | ||
Строка 2477: | Строка 685: | ||
|есть | |есть | ||
|- | |- | ||
- | ! | + | !есть try-finally |
- | |нет | + | |нет<ref>Имитируется макросами через <tt>goto cleanup;</tt></ref> |
- | |нет | + | |нет<ref>Декларируется отстутвие необходимости ввиду налиия RAII; есть в качестве расширения в некоторых реализациях (GCC, MSVC)</ref> |
|есть | |есть | ||
- | |нет | ||
- | |нет | ||
|есть | |есть | ||
|нет | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |- | ||
- | !Абстрактные методы | ||
- | |нет | ||
- | |есть | ||
- | |есть | ||
|есть | |есть | ||
|нет | |нет | ||
- | |есть | ||
|нет | |нет | ||
|нет | |нет | ||
|нет | |нет | ||
|нет | |нет | ||
- | |есть | ||
|- | |- | ||
- | ! | + | !есть понятие связывания подпрограмм (методов класса) на этапе выполнения (динамического связывания) |
|нет<ref>Обычно реализуется через указатели на функции и указатели на структуры с указателями на функции.</ref> | |нет<ref>Обычно реализуется через указатели на функции и указатели на структуры с указателями на функции.</ref> | ||
|есть | |есть | ||
Строка 2512: | Строка 707: | ||
|нет | |нет | ||
|есть | |есть | ||
- | |нет<ref>Комитет ISO утвердил т.н. «объектное расширение» (OO extension). (См.: стандартизация [http://sc22wg13.twi.tudelft.nl ISO Modula-2].) В получившемся языке каждый метод виртуален (взято [http://computer-programming-forum.com/27-modula2/2a715a4b1cce6ba6.htm отсюда]). Однако в канонической Modula-2 даже наследования-то нет (собственно, это одна из фич Oberon).</ref> | ||
|нет | |нет | ||
- | |есть | ||
- | |- | ||
- | !Перегрузка (overloading) | ||
|нет | |нет | ||
- | |есть | ||
- | |есть | ||
- | |есть | ||
- | |нет | ||
- | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |есть | ||
|есть | |есть | ||
|- | |- | ||
- | ! | + | !Тип Запись (struct, record) |
- | + | ||
- | + | ||
|есть | |есть | ||
+ | |есть<ref>Является классом с публичной областью видимости для полчей; если не использовать виртуальные етоды, близок по использованию к структурам в C</ref> | ||
|есть | |есть | ||
|нет | |нет | ||
|есть | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
|есть | |есть | ||
|есть | |есть | ||
- | |- | ||
- | !Конструкция try-finally | ||
- | |нет<ref>Имитируется макросами через <tt>goto cleanup;</tt></ref> | ||
- | |нет<ref>Декларируется отстутвие необходимости ввиду налиия RAII; есть в качестве расширения в некоторых реализациях (GCC, MSVC)</ref> | ||
|есть | |есть | ||
|есть | |есть | ||
- | |нет | ||
|есть | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |- | ||
- | !Раздельная независимая трансляция | ||
|есть | |есть | ||
- | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |есть<ref>С версии 4.0.</ref> | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
|- | |- | ||
- | ! | + | !Оператор loop |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
|есть | |есть | ||
|есть | |есть | ||
Строка 2581: | Строка 737: | ||
|есть | |есть | ||
|- | |- | ||
- | ! | + | !Оператор with |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
|есть | |есть | ||
|есть | |есть | ||
|нет | |нет | ||
- | |нет<ref>Нет в Оберон; учитывая характер изменений, внесённых в Оберон-2, делаем вывод о том, что размеченных объединений в нём нет. </ref> | ||
|есть | |есть | ||
- | |есть<ref name="yes-for-ada-implementation">Есть в Ада; вероятно, есть и в конкретной реализации.</ref> | ||
- | |есть<ref name="yes-for-ada-implementation" /> | ||
- | |- | ||
- | !Перечисления | ||
|есть | |есть | ||
- | + | |нет<ref>Ключевое слово '''with''' означает импортирование классов в текущую область видимости.</ref> | |
- | + | | | |
- | + | ||
- | + | ||
- | + | ||
- | |нет | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | | | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|- | |- | ||
!Процедурное программирование | !Процедурное программирование | ||
Строка 2645: | Строка 775: | ||
|есть | |есть | ||
|есть | |есть | ||
- | |- | ||
- | !Вложенные модули | ||
- | |нет | ||
- | |есть<ref>См. статью [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2073.pdf «Модули в С++»].</ref> | ||
- | |есть | ||
- | |нет (?) | ||
- | |нет<ref name="no-nested-modules-pascal">Вложенными могут быть только подпрограммы, которые не являются библиотечными модулями.</ref> | ||
- | |нет<ref name="no-nested-modules-pascal" /> | ||
- | |нет<ref name="no-nested-modules-pascal" /> | ||
- | |нет<ref name="no-nested-modules-pascal" /> | ||
- | |есть | ||
- | |есть | ||
- | |есть | ||
- | |||
|- | |- | ||
!АТД | !АТД | ||
Строка 2665: | Строка 781: | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
|есть | |есть | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
|- | |- | ||
!Расширяющее программирование | !Расширяющее программирование | ||
Строка 2678: | Строка 794: | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|есть | |есть | ||
Строка 2691: | Строка 807: | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
|есть | |есть | ||
|и | |и | ||
|есть | |есть | ||
+ | | | ||
|нет | |нет | ||
- | + | |есть? | |
- | |есть | + | |
|- | |- | ||
!Компонентное программирование | !Компонентное программирование | ||
Строка 2704: | Строка 820: | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|и | |и | ||
Строка 2717: | Строка 833: | ||
|нет | |нет | ||
|нет | |нет | ||
- | | | + | | |
|нет | |нет | ||
|ч/и | |ч/и | ||
Строка 2734: | Строка 850: | ||
|нет | |нет | ||
|нет | |нет | ||
- | | | + | | |
|есть | |есть | ||
|есть | |есть | ||
Строка 2740: | Строка 856: | ||
!Параллельное программирование | !Параллельное программирование | ||
|нет | |нет | ||
- | |нет | + | |нет |
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
|нет | |нет | ||
|нет | |нет | ||
|нет | |нет | ||
|ч/и? | |ч/и? | ||
- | | | + | | |
- | | | + | | |
|- | |- | ||
- | ! | + | !Рефлективное программирование |
|нет | |нет | ||
|и | |и | ||
|есть | |есть | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|} | |} | ||
:ч/и - частично имитируется | :ч/и - частично имитируется | ||
Строка 2795: | Строка 885: | ||
= Примечания = | = Примечания = | ||
<references /> | <references /> | ||
- | |||
- | {{Курс Языки Программирования}} |