Текущая версия |
Ваш текст |
Строка 1: |
Строка 1: |
- | [[Языки программирования, 08 лекция (от 28 сентября)|Предыдущая лекция]] | [[Языки программирования, 10 лекция (от 05 октября)|Следующая лекция]]
| + | == From Ebaums Inc to MurkLoar. == |
- | =Часть 1. Основные понятия традиционных процедурных ЯП= | + | We at EbaumsWorld consider you as disgrace of human race. |
- | ==Глава 1. Скалярный базис==
| + | Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated. |
- | ===Пункт 8. Функциональный (процедурный) тип данных (продолжение)===
| + | Dig yourself a grave - you will need it. |
- | В [[C++]] указатель на функцию подобен ссылке, можно вызывать любым способом:
| + | |
- | ('''C++''')
| + | |
- | void f() {...}
| + | |
- | ...
| + | |
- | void (*p)();
| + | |
- | p=f;
| + | |
- | (*p)();
| + | |
- | p();
| + | |
- | | + | |
- | ('''Pascal''')
| + | |
- | type PRCI=procedure(integer);
| + | |
- | var f:PRCI;
| + | |
- | f(0);
| + | |
- | | + | |
- | [[Ada]] — нет процедурного типа, но есть альтернатива — родовые модули (пакеты, подпрограммы). Обобщённое (родовое) программирование имеется в [[Ada]], [[С++]], [[С#]]. Статическими параметры родовых модулей могут быть не просто объекты данных, но и типы и подпрограммы. Динамические параметры — объекты данных.
| + | |
- | | + | |
- | Пример: вычисление интеграла
| + | |
- | ('''Ada''')
| + | |
- | generic
| + | |
- | with function f(x:real) return real;
| + | |
- | function INTEGRAL(A,B,EPS:REAL) return real;
| + | |
- | | + | |
- | Ещё можно параметризовать тип данных, так как в Аде их много. Передача подпрограмм делается в Ada при помощи родовых модулей.
| + | |
- | | + | |
- | В Java и C# нет процедурных переменных. А как же ингеграл? В Java нужно унаследовать класс и переопределить функцию.
| + | |
- | | + | |
- | '''Callback''' — аналог динамического связывания. В Обероне использовалось два стиля ООП: на основании RTTI и на основании обработчика (handler) (объекты посылают сообщения друг другу). Обработчик есть процедурная переменная.
| + | |
- | | + | |
- | Понятие обработчика — понятие адреса, а это уже потенциальная ненадёжность. Как бороться с этой ненадёжностью? Ада предлагает статичное решение, но лучше динамическое связывание. И в современных ЯП эта задача решается достаточно интересно.
| + | |
- | | + | |
- | В С# ввели аналог — делегат. Можно рассматривать делегат как коллекцию адресов обектов и ссылок на функции. Чем отличается от процедурного типа? В наборе операций. В классических ЯП можно делать только присваивание и вызов. К делегату можно применять операции сравнения на равенство и неравенство, а также += и -=.
| + | |
- | | + | |
- | В разных ЯП операция неравенства выглядит по-разному (!= (Си) # (Модула) <> (Паскаль) /= (Ада))
| + | |
- | ('''C#''')
| + | |
- | delegate void MyDelegate();
| + | |
- | ...
| + | |
- | MyDelegate e;
| + | |
- | void g;
| + | |
- | void g1;
| + | |
- | void g2;
| + | |
- | e = new MyDelegate(g);
| + | |
- | e += new MyDelegate(g1);
| + | |
- | e += new MyDelegate(g2);
| + | |
- | <p>Если вызвать e, то будут вызваны все три функции. Это отвечает событийной модели событий, при которой те, кому интересно событие, подписываются на него при помощи +=.</p>
| + | |
- | | + | |
- | Для статической функции передаётся указатель/ссылка на объект. В C++ создаётся путаница:
| + | |
- | ('''C++''')
| + | |
- | X x;
| + | |
- | x.f();
| + | |
- | X::f();
| + | |
- |
| + | |
- | В С# и Java можно их вызывать только через имя класса.
| + | |
- | | + | |
- | Делегаты — статическая или не статическая функция? А это никого не волнует. Может быть как статической так и нет. Делегат представляет коллекцию из пар адрес объекта — адрес функции. Таким образом взломать код на С# невозможно.
| + | |
- | | + | |
- | Вернёмся к языку Ada. В ней подпрограммного типа нет. В Ada95 — есть. Зачем, хотя без него можно обойтись, более того, там появилось ООП — для совместимости с другими языками.
| + | |
- | | + | |
- | ===Мораль Главы 1===
| + | |
- | Итак, самый богатый типами данных язык — Turbo Pascal. Чуть меньше их в стандартном Pascal и Ada.
| + | |
- | Мораль: базисные типы — не главное.
| + | |
- | На этом закончим первую главу.
| + | |
- | | + | |
- | ==Глава 2. Составные базисные типы==
| + | |
- | ===Пункт 1. Классификация===
| + | |
- | Наиболее полно удовлетворяют классификации Ада и Паскаль.
| + | |
- | *Массив
| + | |
- | *Запись (объединение)
| + | |
- | *Множество
| + | |
- | *Файл
| + | |
- | *Строка — в С# (System.String) и Джаве (java.lang.String) выглядит как класс
| + | |
- | | + | |
- | В С/C++ - массивы и записи.
| + | |
- | | + | |
- | Общая тенденция: массив — базисная вещь, и от него не отказываются. Запись – расширяется классом.
| + | |
- | | + | |
- | Все остальные вещи уходит в библиотеку. Хеш-таблицы не входят вSTL, так как STL бескомпромиссна в отношении производительности для хэш-таблицы нельзя задать гарантированное время доступа. Это к вопросу, почему в современных стандартных библиотеках очень мало типов данных, потому что их очень трудно реализовать универсально.
| + | |
- | | + | |
- | Массив — единственный полноправный ТД во всех ЯП.
| + | |
- | | + | |
- | === Пункт 2. Массив ===
| + | |
- | В основном будет рассматриваться вектор. Массивы отличаются в разных ЯП набором атрибутов и временем связывания. Набор атрибутов:
| + | |
- | | + | |
- | # Базовый тип
| + | |
- | # Длина
| + | |
- | # L, R — левая и правая границы массива, а также тип индекса
| + | |
- | | + | |
- | Это только основные атрибуты. Например, в Ada ещё есть универсальный атрибут — адрес начала.
| + | |
- | | + | |
- | Операции:
| + | |
- | * Присваивание
| + | |
- | * Копирование
| + | |
- | * Индексирование
| + | |
- | | + | |
- | То есть индексирование — операция, которая принимает качестве параметра тип индекса и возвращает ссылку на объект базового типа.
| + | |
- | | + | |
- | '''([[C++]])'''
| + | |
- | x.operator[](i) — возвращает ссылку //альтернативная запись x[i]
| + | |
- | | + | |
- | Недостаток языка [[Pascal]] — статичность связывания всех атрибутов, в том числе длины. А также то, что атрибуты являются частью типа. На эти проблемы обратил внимание [[Брайан Керниган]] в тексте «16 причин, по которым Pascal не является моим любимым языком программирования». В любых расширениях Pascal были возможность разделять программы на модули и <!-- ??? --> .
| + | |
- | | + | |
- | Почему Вирт пошёл на такой шаг?
| + | |
- | * Это позволяет реализовать массивы до предела эффективно
| + | |
- | * Pascal планировался как язык для обучения программированию
| + | |
- | | + | |
- | Пример открытого массива как параметра процедуры:
| + | |
- | | + | |
- | '''([[Modula-2]])'''
| + | |
- | procedure SCAL(var X, Y : ARRAY OF REAL) : REAL;
| + | |
- | | + | |
- | Тут отсутствует описание индекса. Соответствующим параметром может быть любой массив с соответствующим базовым типом. Индексным типом может быть только дискретный тип данных. Двумерных открытых массивов нет. Для выяснения длины массива есть High.
| + | |
- | | + | |
- | В языке [[Oberon]] то же самое, только определение массива до предела упростилось.
| + | |
- | '''([[Oberon]])'''
| + | |
- | ARRAY N OF T
| + | |
- | N — константа. Таким образом, мы только регулируем только длину, т. е. R + 1, а L = 0 и IndexT всегда INTEGER.
| + | |
- | | + | |
- | Также есть открытые массивы, только теперь есть ещё многомерные открытые массивы. Тип индекса и в [[Modula-2]], и в [[Oberon]] привязаны к Integer. Для объектов данных является частью типа. Позиция C такая же, только без контроля.
| + | |
- | | + | |
- | Для открытых массивов возможна только квазистатическая проверка, и компиляторы [[Modula]] и [[Oberon]] их вставляют. Понятие с одной стороны упрощается, с другой стороны остаётся под контролем.
| + | |
- | | + | |
- | Наиболее мощным является понятие массива в [[Ada]].
| + | |
- | | + | |
- | ==== Массивы в [[С#]], [[Delphi]], [[Java]] ====
| + | |
- | | + | |
- | Есть простые типы, есть референциальные типы. Ими являются все классы, интерфейсы и массивы. Массив есть ссылка.
| + | |
- | | + | |
- | ('''Java''')
| + | |
- | T[] имя;
| + | |
- | Int[] a={1,2,5,10};
| + | |
- | a = new int[n];
| + | |
- | a = b;
| + | |
- | | + | |
- | Cвязываются базовый тип, тип индекса. Длина — динамический параметр. Операция индексирования является контролируемой. Присваивание — присваивание ссылок, а не копирование значений. Операция опасна, если отсутствует сборка мусора (в [[Delphi]] есть сборка мусора для динамических массивов).
| + | |
- | | + | |
- | А если хочется копировать, существует полная иерархия объектов, которая начинается с корневого объекта ([[Java]], [[С#]] — Object, [[Delphi]] — TObject) — класс, который прямо или косвенно наследуется другим классом. То же было в [[SmallTalk]]. И это решается на уровне Object, у которого есть операция clone. А если мы хотим запретить копирование объектов, то можно перегрузить clone.
| + | |
- | | + | |
- | В этих языках также есть понятие коллекций, которые могут легко менть свои границы. Массив тоже может расти и сужаться — есть GetLength, SetLength. Но это нужно исключительно для гибкости. В общем случае это просто кусок памяти, который ведёт себя достаточно консервативно.
| + | |
- | | + | |
- | {{Языки Программирования}}
| + | |
- | {{Lection-stub}}
| + | |