Редактирование: Сравнение Языков Программирования
Материал из eSyr's wiki.
Внимание: Вы не представились системе. Ваш IP-адрес будет записан в историю изменений этой страницы.
ПРЕДУПРЕЖДЕНИЕ: Длина этой страницы составляет 31 килобайт. Страницы, размер которых приближается к 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 | ||
Строка 26: | Строка 26: | ||
'''delta''' Delta '''range''' Low .. High | '''delta''' Delta '''range''' Low .. High | ||
- | + | === ОБЕРОН-2 и ОБЕРОН: === | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
; Отличия: | ; Отличия: | ||
; В Оберон-2 добавлены: | ; В Оберон-2 добавлены: | ||
Строка 100: | Строка 54: | ||
+, -, *, /, 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 | ||
Строка 113: | Строка 67: | ||
END | END | ||
- | === | + | === Массивы. Длина массива - статический или динамический атрибут. === |
+ | === Управление памятью === | ||
+ | Классы памяти: | ||
- | + | '''Статическая''' | |
- | + | Всё что связано со словом «статический» размещается в блоке статической памяти. Время жизни – от начала программы либо момента первого входа в блок, и до конца программы. | |
- | + | ||
- | + | ||
- | + | '''Квазистатическая''' | |
+ | Квазистатическая память связана с понятием блока: переменные связана с этим блоком (от момента объявления, точнее, прохода code flow через объявление, до выхода из блока). Размещаются в стеке. | ||
- | + | '''Динамическая''' | |
- | + | Время жизни зависит от процедур (ручное управление памятью) или от сборщика мусора. | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | ;Ссылочные типы<ref>Иногда говорят «референциальные типы», здесь использован вариант перевода из msdn.</ref> (значения, на которые указывает ссылочный тип (в частности, экземпляры классов), располагаются в куче): | ||
- | : Класс. | ||
- | : Массив (является объектом, экземпляром абстрактного класса Array). | ||
- | : Интерфейс. | ||
- | : И некоторые другие. | ||
- | == Массивы == | ||
- | === Длина массива — статический или динамический атрибут === | ||
- | '''Си++''': длина массива - только статический атрибут. <br> | ||
- | '''Оберон''', '''Модула-2''': динамический атрибут только для формальных параметров, в остальных случаях - статический. <br> | ||
- | '''Ада''', '''Java''', '''C#''': может быть и тем и другим. <br> | ||
- | <br> | ||
- | '''Замечание из методички''': <br> | ||
- | в языках Оберон и Модула-2 длина формальных параметров — открытых массивов является динамическим атрибутом. <br> | ||
- | В других случаях длина массива — статический атрибут. <br> | ||
- | В Аде формальные параметры неограниченных типов-массивов также имеют динамический атрибут-длину (равно как и динамические массивы-локальные переменные). <br> | ||
- | <br> | ||
- | '''Пример''' динамического массива в языке Java (или C#): | ||
- | void f(int N) { | ||
- | byte [] dynArray = new byte [N]; | ||
- | // ...обработка ... | ||
- | } | ||
=== ОБЕРОН И ОБЕРОН-2 === | === ОБЕРОН И ОБЕРОН-2 === | ||
Строка 261: | Строка 98: | ||
ARRAY Ln OF T | ARRAY Ln OF T | ||
- | Массивы, объявленные без указания длины, называются открытыми массивами. Они могут использоваться только в качестве базового типа указателя, типа элементов открытых массивов и типа формального параметра | + | Массивы, объявленные без указания длины, называются открытыми массивами. Они могут использоваться только в качестве базового типа указателя, типа элементов открытых массивов и типа формального параметра |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
=== Указатели === | === Указатели === | ||
- | Ада, C, C++, C#, Delphi, Оберон | + | Ада, C, C++, C#, Delphi, Оберон |
Указатели языка Ада 83 ссылаются только на объекты из | Указатели языка Ада 83 ссылаются только на объекты из | ||
Строка 307: | Строка 115: | ||
ТипУказатель = 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 === | ||
- | Примечание: в отличие от нижеследующих языков (таких как Pascal / Delphi и Modula-2), в ADA конструкция '''with''' не входит в операторный базис, а служит для подключения пакетов; см. [[#anchor_ada_with|раздел 7]]. | ||
- | '''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; | ||
- | '''<nowiki><<</nowiki>'''Label'''<nowiki>>></nowiki>''' | ||
- | |||
- | Циклы устроены посложнее: | ||
- | |||
- | 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; | ||
- | |||
- | ''(Замечание: именовать циклы необязательно.)'' | ||
- | |||
- | === ОБЕРОН И ОБЕРОН-2 === | ||
- | Операторы в последовательности операторов идут через точку с запятой. В конце последовательности должна стоять точка. | ||
- | |||
- | Пайп-символы «|» — это обязательная деталь конструкций CASE и WITH (они разделяют альтернативные варианты, за исключением умолчательного, задаваемого после ключевого слова ELSE). | ||
- | IF Выражение THEN ПоследовательностьОператоров | ||
- | {ELSIF Выражение THEN ПоследовательностьОператоров} | ||
- | [ELSE ПоследовательностьОператоров] | ||
- | END. | ||
- | |||
- | CASE ch OF | ||
- | "A" .. "Z": ReadIdentifier | | ||
- | "0" .. "9": ReadNumber | | ||
- | "'", '"': ReadString | ||
- | ELSE SpecialCharacter | ||
- | END. | ||
- | |||
- | WHILE Выражение DO | ||
- | ПоследовательностьОператоров | ||
- | END. | ||
- | |||
- | REPEAT | ||
- | ПоследовательностьОператоров | ||
- | UNTIL Выражение. | ||
- | |||
- | FOR v := начало TO конец BY шаг DO | ||
- | ПоследовательностьОператоров | ||
- | END. | ||
- | ''(* Присутствует только в Оберон-2 *)'' | ||
- | |||
- | LOOP | ||
- | ПоследовательностьОператоров | ||
- | END. | ||
- | ''(* Вечный цикл; для выхода используется ключевое слово EXIT *)'' | ||
- | |||
- | WITH | ||
- | Дискриминант: Значение1 DO ПоследовательностьОператоров1 | | ||
- | Дискриминант: Значение2 DO ПоследовательностьОператоров2 | ||
- | ELSE ПоследовательностьОператоров3 | ||
- | END. | ||
- | ''(* Является подобием оператора CASE-OF по дискриминанту'' | ||
- | '' размеченного объединения; присутствует только в Оберон-2 *)'' | ||
- | |||
- | === Modula-2 === | ||
- | |||
- | Полностью совпадает с Обероном-2, за исключением WITH, определяемого так: | ||
- | WITH ПеременнаяСтруктурногоТипа DO | ||
- | ПоследовательностьОператоров | ||
- | Поле1:= Значение1; | ||
- | ПоследовательностьОператоров | ||
- | Поле2:= Значение2; | ||
- | … | ||
- | END. | ||
- | ''(* Поле1, Поле2, итд. — поля переменной «ПеременнаяСтруктурногоТипа»;'' | ||
- | '' конструкция с аналогичным поведением есть в Pascal и Delphi *)'' | ||
- | |||
- | === Pascal и Delphi === | ||
- | |||
- | '''if''' condition1 '''then begin''' | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | '''end''' ''{ заметьте, точки с запятой нет }'' | ||
- | '''else if''' condition2 '''then begin''' | ||
- | … | ||
- | '''end''' | ||
- | '''else begin''' | ||
- | … | ||
- | '''end'''; ''{ if-блок закончен, точка с запятой есть }'' | ||
- | |||
- | '''case''' value1 '''of''' | ||
- | constant1: '''begin''' | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | '''end'''; | ||
- | |||
- | constant2: '''begin''' | ||
- | … | ||
- | '''end'''; | ||
- | |||
- | … | ||
- | |||
- | '''else begin''' | ||
- | … | ||
- | '''end'''; | ||
- | '''end'''; | ||
- | |||
- | '''goto''' label1; ''{ да, в стандарте Паскаля это было }'' | ||
- | |||
- | never_executed_statement1; | ||
- | never_executed_statement2; | ||
- | … | ||
- | |||
- | label1: | ||
- | |||
- | '''for''' variable1 := constant1 '''to''' constant2 '''do begin''' | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | '''end'''; ''{ если constant1 > constant2, используется '''downto''' }'' | ||
- | |||
- | '''while''' continuation '''do begin''' | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | '''end'''; | ||
- | |||
- | '''repeat''' | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | '''until''' discontinuation; | ||
- | ''{ здесь, discontinuation означает условие останова, а не'' | ||
- | '' продолжения (как, например, в цикле предыдущего типа);'' | ||
- | '' также заметьте, что скобки '''begin''' / '''end''' тут не нужны }'' | ||
- | |||
- | '''with''' struct1.substruct1.subsubstruct1 '''do begin''' | ||
- | field1 = value1; | ||
- | field2 = value2; | ||
- | … | ||
- | '''end;''' | ||
- | ''{ field1 и field2 — это поля структуры struct1.substruct1.subsubstruct1;'' | ||
- | '' в этом блоке они перекрывают собой любые переменные с теми же именами }'' | ||
- | |||
- | === C и C++ === | ||
- | |||
- | if (condition1) { | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | } | ||
- | else if (condition2) { | ||
- | … | ||
- | } | ||
- | else { | ||
- | … | ||
- | } | ||
- | |||
- | return; ''// возврат из void-функции'' | ||
- | return value1; ''// возврат из функции, отдающей значение'' | ||
- | |||
- | switch (value1) { | ||
- | case constant1: | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | break; | ||
- | |||
- | case constant2: | ||
- | … | ||
- | break; | ||
- | |||
- | … | ||
- | |||
- | default: | ||
- | … | ||
- | break; | ||
- | } | ||
- | ''// также вместо break можно использовать return (выходим не только из switch-блока, но и из функции).'' | ||
- | |||
- | goto label1; | ||
- | |||
- | never_executed_statement1; | ||
- | never_executed_statement2; | ||
- | … | ||
- | |||
- | label1: | ||
- | |||
- | for (initializer; continuation; increment) { | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | } | ||
- | ''// любые из трёх выражений в заголовке цикла могут пустовать.'' | ||
- | ''// например, for ( ; ; ) {} даст вечный цикл.'' | ||
- | |||
- | do { | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | } while (continuation); | ||
- | |||
- | while (continuation) { | ||
- | statement1; | ||
- | statement2; | ||
- | … | ||
- | } | ||
- | |||
- | === for в C# и Java === | ||
- | |||
- | В '''Java''' используется 2 формы оператора цикла for. | ||
- | Первая форма полностью соответствует оператору for языка Си++: | ||
- | for (e1; e2; e3) S | ||
- | Вторая форма появилась в J2SE 5.0 (вместе с generic'ами) и используется для поэлементного | ||
- | просмотра коллекций (цикл for-each). Она имеет вид; | ||
- | for (T v: Coll) S | ||
- | Здесь Coll — коллекция элементов (типа T или приводимых к типу T). | ||
- | Переменная v на каждой итерации цикла принимает значение очередного | ||
- | элемента коллекции. | ||
- | Для того, чтобы объекты класса-коллекции могли появляться в цикле | ||
- | for-each, класс должен реализовать интерфейс Iterable. | ||
- | |||
- | Для того, чтобы for можно было аналогичным образом использовать в '''C#''', коллекция должна реализовывать интерфейс IEnumerable (конкретно метод GetEnumerator) | ||
- | |||
- | // метод класса, который мы хотим сделать итеративным | ||
- | public System.Collections.IEnumerator GetEnumerator() | ||
- | { | ||
- | for (int i = 0; i < 10; i++) | ||
- | { | ||
- | yield return i; | ||
- | } | ||
- | } | ||
- | |||
- | Здесь yield преобразует int в объект класса IEnumerator. Кроме того, внутреннее состояние функции запоминается и в следующий раз выполнение функции будет продолжено с того состояния и места, где функция вышла в прошлый раз. yield может вызываться только в теле for. | ||
== Процедурные абстракции == | == Процедурные абстракции == | ||
- | |||
- | === Передача параметров в подпрограммы === | ||
- | |||
- | Для каждой подпрограммы указывается набор формальных параметров. Можно рассматривать формальные параметры как локальные переменные тела подпрограммы. При вызове подпрограммы указывается список фактических параметров. Соответствие между фактическими и формальными параметрами выполняется по позиции в списке: первый фактический параметр соответствует первому формальному параметру и т. д. Такой способ называется ''позиционным''. Язык С#, начиная с версии 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: | Строка 140: | ||
a.f(0); // вторая функция | a.f(0); // вторая функция | ||
- | Отличие перегрузки от замещения | + | Отличие перегрузки от замещения состоит во-первых, в том, что |
- | + | перегрузка обрабатывается статически (на этапе трансляции), в во-вторых, | |
- | + | при замещении речь идет о разных областях видимости: базовый класс с | |
- | + | объявлением виртуального метода (объемлющая область видимости) и | |
- | + | производный класс с замещающим методом (вложенная область видимости). | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Определение новых типов данных. Логические модули. Классы == | == Определение новых типов данных. Логические модули. Классы == | ||
Строка 799: | Строка 157: | ||
'''subtype''' String_10 '''is''' My_String ( 0 .. 10 ); ''-- Подтип типа My_String, состоящий из 11 элементов.'' | '''subtype''' String_10 '''is''' My_String ( 0 .. 10 ); ''-- Подтип типа My_String, состоящий из 11 элементов.'' | ||
'''type''' Money '''is''' '''delta''' 1/100 '''range''' 0.0 ... 10000.0 | '''type''' Money '''is''' '''delta''' 1/100 '''range''' 0.0 ... 10000.0 | ||
- | |||
- | Ключевое слово '''Limited''' означает, что у новоявленного типа нет стандартных операций до тех пор, пока программист сам их не опишет. | ||
В языке Ada есть мощный механизм пакетов, и этим он, несмотря на то, что основан на Pascal, совсем на него не похож. Пакеты заимствованы из других языков. Они похожи на классы тем, что являются средством абстракции, позволяющем инкапсулировать сложность внутри пакета, предоставив наружу только интерфейс. Ладно, к сути. | В языке Ada есть мощный механизм пакетов, и этим он, несмотря на то, что основан на Pascal, совсем на него не похож. Пакеты заимствованы из других языков. Они похожи на классы тем, что являются средством абстракции, позволяющем инкапсулировать сложность внутри пакета, предоставив наружу только интерфейс. Ладно, к сути. | ||
Строка 861: | Строка 217: | ||
При подключении потомка родитель-пакет подключается автоматически. | При подключении потомка родитель-пакет подключается автоматически. | ||
- | + | О подключениях. Подключить пакет можно с помощью конструкции '''with'''. | |
'''with''' Points.RandomDistributions; | '''with''' Points.RandomDistributions; | ||
После этого можно будет пользоваться ввсем, что в пакете лежит, через точечную нотацию. Если же вызовов слишком много, то можно влить содержимое пакета в текущую область видимости с помощью '''use''' (только после подключения!). | После этого можно будет пользоваться ввсем, что в пакете лежит, через точечную нотацию. Если же вызовов слишком много, то можно влить содержимое пакета в текущую область видимости с помощью '''use''' (только после подключения!). | ||
Строка 868: | Строка 224: | ||
=== ОБЕРОН И ОБЕРОН-2 === | === ОБЕРОН И ОБЕРОН-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. | ||
+ | |||
+ | Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. | ||
В Обероне-2 стандартная процедура NEW используется, чтобы распределить блоки данных в свободной памяти. Нет, однако, никакого способа явно освободить распределенный блок. Взамен Оберон-среда использует сборщик мусора чтобы найти блоки, которые больше не используются и сделать их снова доступными для распределения. | В Обероне-2 стандартная процедура NEW используется, чтобы распределить блоки данных в свободной памяти. Нет, однако, никакого способа явно освободить распределенный блок. Взамен Оберон-среда использует сборщик мусора чтобы найти блоки, которые больше не используются и сделать их снова доступными для распределения. | ||
- | + | Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон. | |
;Расширение типов | ;Расширение типов | ||
Наиболее важным добавлением(от-но Modula-2) является механизм расширенных типов записи. Он позволяет конструировать новые типы на основе уже существующих и задает определенную степень совместимости между новыми и старыми типами. Предположим, что у нас имеется тип | Наиболее важным добавлением(от-но Modula-2) является механизм расширенных типов записи. Он позволяет конструировать новые типы на основе уже существующих и задает определенную степень совместимости между новыми и старыми типами. Предположим, что у нас имеется тип | ||
Строка 880: | Строка 291: | ||
является (прямым) расширением типа T, и наоборот, T называется (прямым) базовым (base) типом для T’. | является (прямым) расширением типа T, и наоборот, T называется (прямым) базовым (base) типом для T’. | ||
- | == | + | == Инкапсуляция и абстрактные типы данных == |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | == | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Модульность и раздельная трансляция == | == Модульность и раздельная трансляция == | ||
Строка 1106: | Строка 306: | ||
=== Модульность === | === Модульность === | ||
- | + | ОБЕРОН И ОБЕРОН-2 | |
- | + | Модуль - совокупность объявлений констант, типов, переменных и процедур вместе с последовательностью операторов, предназначенных для присваивания начальных значений переменным. Модуль представляет собой текст, который является единицей компиляции. | |
Модуль = MODULE идент ";" [СписокИмпорта] ПоследовательностьОбъявлений | Модуль = MODULE идент ";" [СписокИмпорта] ПоследовательностьОбъявлений | ||
Строка 1163: | Строка 363: | ||
Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. | Загруженный модуль может вызывать команду незагруженного модуля, задавая ее имя как строку. Специфицированный модуль при этом динамически загружается и выполняется заданная команда. Динамическая загрузка позволяет пользователю запустить программу как небольшой набор базисных модулей и расширять ее, добавляя последующие модули во время выполнения по мере необходимости. | ||
Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон. | Интерфейс модуля (объявления экспортируемых объектов) извлекается из модуля так называемым смотрителем, который является отдельным инструментом среды Оберон. | ||
- | |||
- | ==== 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: | Строка 373: | ||
того же блока). | того же блока). | ||
Пример языка 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; | ||
- | } | ||
- | } | ||
'''Семантика завершения''': после возникновения исключения блок, в | '''Семантика завершения''': после возникновения исключения блок, в | ||
Строка 1271: | Строка 378: | ||
происходит в блоках, вызвавших блок с исключением. | происходит в блоках, вызвавших блок с исключением. | ||
Пример языка с семантикой завершения: Си++. | Пример языка с семантикой завершения: Си++. | ||
- | |||
- | '''catch''' (в delphi - '''except''') - то что будет выполнено в случае ошибки в блоке 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 === | ||
- | |||
- | Создание исключения: | ||
- | |||
- | New_Exception: '''exception'''; | ||
- | |||
- | Поднятие/возбуждение исключения<ref>Терминология отличается от принятой в мире языков с C++-подобным синтаксисом. Там: выбрасывание/выброс (throw), здесь — поднятие/возбуждение (raise).</ref>: | ||
- | |||
- | '''raise''' New_Exception; | ||
- | |||
- | Отлов исключения: | ||
- | |||
- | '''begin''' | ||
- | Rise_Exception; | ||
- | '''exception''' | ||
- | '''when''' New_Exception => | ||
- | Do_Smth; | ||
- | '''end'''; | ||
- | |||
- | Отлов исключения так же может иметь такой вид: | ||
- | |||
- | '''when''' Error: Error_Name => | ||
- | |||
- | Однако, что он означает я до конца не понял, но на экзамене это вряд ли нужно будет. Кому интересно, брал [http://en.wikibooks.org/wiki/Ada_Programming/Exceptions здесь.] | ||
== Наследование типов и классов == | == Наследование типов и классов == | ||
- | |||
- | === 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++. В Ada, C#, Delphi, Java множественное наследование поддерживается только для интерфейсов<ref>По крайней мере в контексте Java более корректно будет говорить не о наследовании ('''extends'''), а реализации ('''implements''') или частичной реализации интерфейса (последнее возможно только для абстрактных классов)</ref>. | ||
== Динамическая идентификация типа == | == Динамическая идентификация типа == | ||
- | |||
- | Динамическая идентификация типа данных (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] |
Объявляем шаблон: | Объявляем шаблон: | ||
Строка 1688: | Строка 417: | ||
'''procedure''' Instance_Swap '''is''' '''new''' Swap (Float); | '''procedure''' Instance_Swap '''is''' '''new''' Swap (Float); | ||
'''procedure''' Instance_Swap '''is''' '''new''' Swap (Day_T); | '''procedure''' Instance_Swap '''is''' '''new''' Swap (Day_T); | ||
- | |||
- | Можно так же указывать, какие подпрограммы должны быть определены для обобщенного типа: | ||
- | |||
- | '''generic''' | ||
- | '''type''' Multiplable_T '''is''' '''private'''; ''-- Generic formal type parameter'' | ||
- | '''with''' '''function''' "*" ( X, Y: Multiplable_T) '''return''' Multiplable_T; | ||
:Оператор loop определяет повторное выполнение последовательности операторов. | :Оператор loop определяет повторное выполнение последовательности операторов. | ||
- | :Операторы with выполняют последовательность операторов в зависимости от результата проверки типа и применяют охрану типа к каждому вхождению проверяемой переменной внутри этой последовательности операторов. | + | :Операторы with выполняют последовательность операторов в зависимости от результата проверки типа и применяют охрану типа к каждому вхождению проверяемой переменной внутри этой последовательности операторов. |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
== Итоговая таблица == | == Итоговая таблица == | ||
Строка 2452: | Строка 426: | ||
{| border="1" | {| border="1" | ||
! | ! | ||
- | ! | + | !C |
- | !C++ | + | !C++ |
!C# | !C# | ||
!Java | !Java | ||
Строка 2464: | Строка 438: | ||
!Ada95 | !Ada95 | ||
|- | |- | ||
- | ! | + | !есть оператор перехода «goto метка» |
|есть | |есть | ||
- | |есть | ||
- | |есть | ||
- | |нет<ref>Есть break '''label'''; и continue '''label''';, где '''label''' ставится с двоеточием перед началом цикла и указывает, какой именно цикл (в случае continue — итерацию какого именно цикла) среди тех, в которые вложен данный оператор, нужно прервать. В Java есть зарезервированное слово goto, но оно не несёт никаких функций — оператора безусловного перехода в языке нет (однако переход осуществить можно, см. [http://www.docjar.com/docs/api/com/sun/org/apache/bcel/internal/generic/GOTO.html]).</ref> | ||
|есть | |есть | ||
|есть | |есть | ||
- | |нет | ||
- | |нет | ||
|нет | |нет | ||
|есть | |есть | ||
|есть | |есть | ||
- | |- | ||
- | !Конструкция "свойство" (property) | ||
|нет | |нет | ||
- | |нет | ||
- | |есть | ||
|нет | |нет | ||
|нет | |нет | ||
|есть | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |- | ||
- | !Абстрактные методы | ||
- | |нет | ||
- | |есть | ||
- | |есть | ||
- | |есть | ||
- | |нет | ||
- | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
|есть | |есть | ||
|- | |- | ||
- | ! | + | !есть try-finally |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|нет | |нет | ||
- | |есть | ||
|нет | |нет | ||
|есть | |есть | ||
- | |нет | + | |нет??? |
- | | | + | |? |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|есть | |есть | ||
|нет | |нет | ||
Строка 2529: | Строка 464: | ||
|есть | |есть | ||
|- | |- | ||
- | ! | + | !есть понятие динамического связывания подпрограмм (методов класса) |
- | | | + | |? |
|есть | |есть | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | |? |
|есть | |есть | ||
|нет | |нет | ||
- | |нет | ||
- | |нет | ||
- | |есть | ||
- | |есть | ||
- | |- | ||
- | !Конструкция try-finally | ||
- | |нет<ref>Имитируется макросами через <tt>goto cleanup;</tt></ref> | ||
- | |нет<ref>Декларируется отстутвие необходимости ввиду налиия RAII; есть в качестве расширения в некоторых реализациях (GCC, MSVC)</ref> | ||
- | |есть | ||
|есть | |есть | ||
|нет | |нет | ||
- | |есть | ||
|нет | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |- | ||
- | !Раздельная независимая трансляция | ||
|есть | |есть | ||
- | |есть | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |есть<ref>С версии 4.0.</ref> | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
- | |нет | ||
|- | |- | ||
- | !Тип | + | !Тип Запись |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
- | + | ||
|есть | |есть | ||
|есть | |есть | ||
+ | | | ||
+ | | | ||
+ | | | ||
|- | |- | ||
- | ! | + | !Оператор loop |
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | | | + | | |
+ | | | ||
+ | | | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
|- | |- | ||
- | ! | + | !Оператор with |
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
+ | | | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|- | |- | ||
!Процедурное программирование | !Процедурное программирование | ||
Строка 2625: | Строка 521: | ||
|есть | |есть | ||
|есть | |есть | ||
+ | | | ||
|есть | |есть | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
|- | |- | ||
!Модульное программирование | !Модульное программирование | ||
Строка 2638: | Строка 534: | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|- | |- | ||
!АТД | !АТД | ||
Строка 2665: | Строка 547: | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
|есть | |есть | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
|- | |- | ||
!Расширяющее программирование | !Расширяющее программирование | ||
Строка 2678: | Строка 560: | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|есть | |есть | ||
Строка 2691: | Строка 573: | ||
|есть | |есть | ||
|есть | |есть | ||
- | | | + | | |
|есть | |есть | ||
|и | |и | ||
|есть | |есть | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
|- | |- | ||
!Компонентное программирование | !Компонентное программирование | ||
Строка 2704: | Строка 586: | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|и | |и | ||
Строка 2717: | Строка 599: | ||
|нет | |нет | ||
|нет | |нет | ||
- | | | + | | |
|нет | |нет | ||
|ч/и | |ч/и | ||
Строка 2730: | Строка 612: | ||
|и | |и | ||
|нет | |нет | ||
+ | | | ||
|нет | |нет | ||
|нет | |нет | ||
|нет | |нет | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
|- | |- | ||
!Параллельное программирование | !Параллельное программирование | ||
|нет | |нет | ||
- | |нет | + | |нет |
|есть | |есть | ||
|есть | |есть | ||
+ | | | ||
|нет | |нет | ||
|нет | |нет | ||
|нет | |нет | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
|- | |- | ||
- | ! | + | !Рефлективное программирование |
|нет | |нет | ||
|и | |и | ||
|есть | |есть | ||
|и | |и | ||
- | | | + | | |
|и | |и | ||
|и | |и | ||
|и | |и | ||
- | | | + | | |
- | | | + | | |
- | | | + | | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
|} | |} | ||
:ч/и - частично имитируется | :ч/и - частично имитируется | ||
:и - имитируется | :и - имитируется | ||
- | |||
- | = Примечания = | ||
- | <references /> | ||
- | |||
- | {{Курс Языки Программирования}} |