Обобщенное программирование это с

Обобщенное программирование

Обобщённое программирование — парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. В том или ином виде поддерживается разными языками программирования. Возможности обобщённого программирования впервые появились в 70-х годах в языках CLU и Ada, а затем во многих объектно-ориентированных языках, таких как C++, D и языках для платформы .NET.

Общий механизм

Средства обобщённого программирования реализуются в языках программирования в виде тех или иных синтаксических средств, дающих возможность описывать данные (типы данных) и алгоритмы (процедуры, функции, методы), параметризуемые типами данных. У функции или типа данных явно описываются формальные параметры-типы. Это описание является обобщённым и в исходном виде непосредственно использовано быть не может.

В тех местах программы, где обобщённый тип или функция используется, программист должен явно указать фактический параметр-тип, конкретизирующий описание. Например, обобщённая процедура перестановки местами двух значений может иметь параметр-тип, определяющий тип значений, которые она меняет местами. Когда программисту нужно поменять местами два целых значения, он вызывает процедуру с параметром-типом «целое число» и двумя параметрами — целыми числами, когда две строки — с параметром-типом «строка» и двумя параметрами — строками. В случае с данными программист может, например, описать обобщённый тип «список» с параметром-типом, определяющим тип хранимых в списке значений. Тогда при описании реальных списков программист должен указать обобщённый тип и параметр-тип, получая, таким образом, любой желаемый список с помощью одного и того же описания.

Читайте также:  Программирование старлайн а91 второго брелка

Компилятор, встречая обращение к обобщённому типу или функции, выполняет необходимые процедуры статического контроля типов, оценивает возможность заданной конкретизации и при положительной оценке генерирует код, подставляя фактический параметр-тип на место формального параметра-типа в обобщённом описании. Естественно, что для успешного использования обобщённых описаний фактические типы-параметры должны удовлетворять определённым условиям. Если обобщённая функция сравнивает значения типа-параметра, любой конкретный тип, использованный в ней, должен поддерживать операции сравнения, если присваивает значения типа-параметра переменным — конкретный тип должен обеспечивать корректное присваивание.

Способы реализации

Известно два основных способа реализации поддержки обобщённого программирования в компиляторе.

  • Порождение нового кода для каждой конкретизации. В этом варианте компилятор рассматривает обобщённое описание как текстовый шаблон для создания вариантов конкретизаций. Когда компилятору требуется новая конкретизация обобщённого типа или процедуры, он создаёт новый экземпляр типа или процедуры, чисто механически добавляя туда тип-параметр. То есть, имея обобщённую функцию перестановки элементов, компилятор, встретив её вызов для целого типа, создаст функцию перестановки целых чисел и подставит в код её вызов, а затем, встретив вызов для строкового типа — создаст функцию перестановки строк, никак не связанную с первой. Этот метод обеспечивает максимальное быстродействие, поскольку варианты конкретизаций становятся разными фрагментами программы, каждый из них может быть оптимизирован для своего типа-параметра, к тому же в код не включаются никакие лишние элементы, связанные с проверкой или преобразованием типов на этапе исполнения программы. Недостатком его является то, что при активном использовании обобщённых типов и функций с различными типами-параметрами размер откомпилированной программы может очень сильно возрастать, поскольку даже для тех фрагментов описания, которые для разных типов не различаются, компилятор всё равно генерирует отдельный код. Этот недостаток можно затушевать путём частичной генерации общего кода (часть обобщённого описания, которая не зависит от типов-параметров, оформляется специальным образом и по ней компилятор генерирует единый для всех конкретизаций код). Зато данный механизм даёт естественную возможность создания специальных (обычно — сильно вручную оптимизированных) конкретизаций обобщённых типов и функций для некоторых типов-параметров.
  • Порождение кода, который во время исполнения выполняет преобразование фактических параметров-типов к одному типу, с которым фактически и работает. В этом случае на этапе компиляции программы компилятор лишь проверяет соответствие типов и включает в код команды преобразования конкретного типа-параметра к общему типу. Код, определяющий функционирование обобщённого типа или функции, имеется в откомпилированной программе в единственном экземпляре, а преобразования и проверки типов выполняются динамически, во время работы программы. В этом варианте порождается, как правило, более компактный код, но программа оказывается в среднем медленнее, чем в первом варианте, из-за необходимости выполнения дополнительных операций и меньших возможностей оптимизации. Кроме того, в компилированный код для типов-параметров далеко не всегда включается динамическая информация о типах (в первом варианте она есть, если вообще поддерживается, поскольку конкретизации для каждого типа-параметра различны), что определяет некоторые ограничения на применение обобщённых типов и функций. Подобные ограничения есть, например, в Java.
Читайте также:  Адаптивный шаблон

Обобщённое программирование в языках

C++

В языке C++ обобщённое программирование основывается на понятии «шаблон», обозначаемом ключевым словом template. Широко применяется в стандартной библиотеке C++ (см. STL), а также в сторонних библиотеках boost, Александр Степанов.

В качестве примера приведём обобщённую функцию, возвращающую большее значение из двух.

Java

Java предоставляет средства обобщённого программирования, синтаксически основанные на C++, начиная с версии J2SE 5.0. В этом языке имеются generics или «контейнеры типа T» — подмножество обобщённого программирования.

.NET

На платформе .NET средства обобщённого программирования появились в версии 2.0.

Пример на C#

D

В языке «D» средства обобщённого программирования значительно эволюционировали в сравнении с С++, как в процедурной, так и в объектно ориентированной составляющей. Значительно проще стало и лингвистическое представление.

Пример рекурсивной генерации на основе шаблонов D:

Wikimedia Foundation . 2010 .

Источник

Обобщения C#

Обобщения (generics) необходимы в тех случаях, когда мы не можем заранее знать тип данных, который будем использовать. Они есть во многих языках программирования.

Пример использования обобщений

Представим ситуацию, что заказчик дал нам работу в виде создания ПО для работы с продажей различных видов товаров, по различной цене.

Все мы знаем (а может предстоит узнать), что заказчики очень изменчивые люди в плане своих проектов. Сегодня он скажет сделать цену в виде целого числа, а завтра ему понадобятся еще и копейки в виде дробной.

Что делать в таком случае? Переписывать логику? Ведь если мы изменим тип данных, то вся программа сломается и будет куча ошибок из-за несоответствия типов в классе «продажи».

Выход из данной ситуации есть — и то это шаблоны!

Пример реализации

Давайте рассмотрим приведенный выше пример подробнее и реализуем его на практике

Реализация без шаблонов

Начнём с того, что мы не знаем, про обобщения и реализуем поставленную задачу без них.

Опишем поставленную задачу:

Программа имеет возможность продажи различных продуктов по заданной цене , например “хлеб” за 45 рублей. Исходя из этого можно понять, что мы имеем некий класс, назовем его Product , который имеет поля — Name (наименование продукта ), Price (цена продукта) и один метод Sell (метод продажи). (Рис.1)

Рис.1 Код класса Product

Попробуем использовать написанный код

Создадим продукт , который будет являться хлебом , стоить он будет 45 рублей ( целое число), затем вызовем метод Sell() (Рис.2)

Рис.2 Код работы с классом Product

Запустим программу и увидим , что мы продали хлеб за 45 рублей. (Рис.3)

Рис.3 Вывод программы

Проблема, которая может возникнуть

А теперь представим , что заказчик сообщил о том, что цену на хлеб необходимо указать с копейками.

У нас есть (пока что) лишь один выход из данной ситуации — изменить всю логику класса , задав тип данных вместо целого числа (int) — дробное (float). Действительно, если проделать данные действия , то заказчик будет удовлетворён , но что если логика продажи будет очень большой и нам из-за прихоти заказчика придется все переписывать? так как лично я достаточно ленивый человек — делать этого мне не очень будет хотеться.

Теперь вот как раз таки обобщения выступают нам как «ангел хранитель», который поможет нам спасти себя от рутинной работы обновления логики каждый раз, когда заказчик будет менять свои запросы.

Использование обобщений

Угловые скобки в описании class Product указывают, что класс является обобщенным, а тип T, заключенный в угловые скобки, будет использоваться этим классом. Необязательно использовать именно букву T, это может быть и любая другая буква. Причем сейчас на этапе написания кода нам неизвестно, что это будет за тип, это может быть любой тип. Поэтому параметр T в угловых скобках еще называется универсальным параметром, так как вместо него можно подставить любой тип.

Изменим структуру нашего класса с использованием обобщения (Рис.4)

Рис.4 использование обобщения в классе Product

Теперь мы увидим ошибку в методе Main (Рис.5)

Рис.5 Ошибка

Данная ошибка появилась из-за того, что мы не используем int как было раньше, теперь мы используем обобщение с типом T , следовательно нам необходимо, изменить объявление объекта класса Product, следующим образом (Рис.6)

Рис.6 Обновленный код

В угловых скобках мы указали тип данных double , исходя из этого цена продукта T Price в классе Product, грубо говоря подставит тип данных double вместо T и в последующем будет его использовать.

Запустим программу и увидим, что мы продали товар за 45.5 рублей (Рис.7)

Рис.7 Вывод программы

Теперь, мы можем для цены Price использовать любой тип данных для каждого нового объекта класса, например создадим новый объект и в качестве T укажем тип данных string

Создадим объект класса Product назовем его milk и укажем название name — «Молоко», а цену Price — «Нет в наличии. 0 рублей», затем вызовем метод Sell (Рис.8)

Рис.8 новый объект класса

Запустим программу и увидим, что все работает (Рис.9)

Рис.8 Запуск программы

В рамках такого небольшого примера, трудно ‘разойтись’, но думаю в целом стало немного понятнее.

Также ярким примером использования шаблонов можно назвать всем известный класс List , данный класс не знает с каким типом данных он будет работать заранее и при передаче в качестве T любого типа данных, логика не поломается. А вот если бы класс шаблоны не использовал, то для каждого нового типа данных пришлось бы создавать копию класса с практически идентичной логикой, но просто переделанной под другой тип

Вывод

Обобщения присутствует во многих языках программирования. Шаблонизация используется фактически во всех динамических структурах языка C# (списки, очереди, стеки и т. д). Знание этого инструмента программирование поможет вам создавать более универсальные структуры и алгоритмы

Источник

Оцените статью