Главная » Просмотр файлов » И.Г. Головин, И.А. Волкова - Языки и методы программирования

И.Г. Головин, И.А. Волкова - Языки и методы программирования (1160773), страница 32

Файл №1160773 И.Г. Головин, И.А. Волкова - Языки и методы программирования (И.Г. Головин, И.А. Волкова - Языки и методы программирования) 32 страницаИ.Г. Головин, И.А. Волкова - Языки и методы программирования (1160773) страница 322019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 32)

Частичная специализа­ция порождает новый вариант параметризованного шаблона, кото­рый является частным случаем общего шаблона. Набор аргументов,подходящих для частичной специализации, подходит и для общего163шаблона, но является «более точным». Например, общий шаблониспользует просто имя любого типа, а частичная специализация —тип указателя, тип массива, функциональный тип и т. п. Другимвариантом специализации является меньшее число параметров, чемв общем случае, и т.д. Точное определение понятия «более точный»дано в стандарте C++, и здесь мы не будем вдаваться в детали.Пример шаблона, нуждающегося в частичной специализации, —шаблон класса Stack (другой пример — класс DynVector), со­держащий ряд нетривиальных операций. Как уже отмечалось, длялюбого нового типа хранимых элементов порождается новый наборопераций.

Причем для ряда типов эти операции делают одно и то же.Например, для указателей все операции над стеком неразличимы.Однако для каждого указательного типа порождается свой набор, чтоприводит к недопустимому разрастанию машинного кода, которыйпроизводит одни и те же операции.Рассмотрим специализацию стека для указателей. Она будетреализована как частный случай (т. е. как конкретизация шаблономсамого себя) — стек, хранящий указатели типа void*:template <typename Т> class Stack; // общий шаблонtemplate ctypename T> class Stack <T*>// специализация: private Stack <void*> {// наследует конкретизацию общего шаблона// закрытым образомtypedef Stack <void*> BASE;publ i c :explicit Stack(int sz) : BASE(sz) {}T * Pop() { return (T*)BASE::P o p ();}void Push (T * p) { B A S E ::Push (p); }void Swap () {B A S E ::swap ();}// ...

переадресация других методов};Stack <int> s(256); // общий шаблонStack <const char *> strs(64);// частично специализированныйs t r s .P u s h ("sample");10.3. Особенности реализациипараметрического полиморфизма в языкахC# и JavaВ языках C# и Java синтаксис обобщенных типов проще, чемв языке C++, поскольку параметром обобщения здесь может бытьтолько тип (поэтому указывать этот факт не надо):164class и мя-обобщен ного-типа <список-параметров>{ объявления-членов }Конкретизация в C# и Java имеет вид такой же, как и в C++, и рас­сматривается как имя нового типа:class X <Т> { ...

}class Y { ... }// обобщенный тип// обычный типX<Y> s = new X<Y>(); // создан экземпляр конкретного// классаX <Y> si = s; // две ссылки на объект конкретного// классаРассмотрим пример обобщенного типа стек на C# и Java (ис­пользуя код из гл.

7), который несмотря на простоту, демонстрируетхарактерные различия между подходами к параметрическому поли­морфизму в этих двух языках (хотя общего в этих подходах большепо сравнению с шаблонами C++):class Stack<T>{Т [] body;int top;public Stack(int size){body = new T[size];top = 0;}public T Pop() { return b o d y [— top]; }public void Push(T x) { body[top++] = x; }public bool IsEmpty {get { return top ==0; }}public bool IsFull {get { return top == body.Length;}}}Приведем пример использования созданного стека:Stack<int> s = new Stack<int>(16);int [] x = {1,2,3,4,5,6,7};foreach (int k in x) s.Push(k);while (!s.IsEmpty) Console.WriteLine(s.Pop ()) ;Stack <double> sd = new Stack <double>(32);double [] xx = {1.1,2.2,3.3,4.4,5.5,6.6,7.7};foreach (double k in xx) sd.Push(k);while (! sd.

IsEmpty) Console.WriteLine (sd.PopO);165Обратим внимание на два момента.Во-первых, нельзя использовать объекты стеки для храненияразнотипных данных. Универсальный стек (из Obj ect) мог быть ис­пользован для работы с обоими массивами (int [ ] х и double [ ] хх),но в данном примере следует создавать два стека. Попытка записатьв stack<int> целое число будет пресечена транслятором.

Такимобразом, созданный стек безопасен с точки зрения типов. Работаяс таким стеком, можно быть уверенным, что никаких исключений,связанных с неверным преобразованием ссылок, не будет.Во-вторых, получившийся вариант более эффективен вслед­ствие отсутствия неявных операций упаковки в объект типов зна­чений. Ранее эта операция незаметно происходила при обращениик Push (). Сейчас мы имеем свой вариант Push () для каждого видастека. В конечном счете компилятор генерирует отдельный код дляконкретизации типом значений, а также для конкретизации ссылоч­ными типами. Таким образом, если в программе есть конкретизацииStack <double>, Stack<int>, Stack<String>, Stack<char[]>,то будет сгенерировано три набора функций членов: по одному на­бору для каждого типа значений (double, int) и один набор дляссылочных типов (String, char [ ]).

Отметим, что возможностьгенерировать один и тот же код для типов-ссылок связана с тем, чтос точки зрения стека типы отличаются только размером. Если размертипов одинаковый, то код функций, копирующих значения этоготипа, тоже одинаковый.Каждый набор сгенерированных методов не использует функцииупаковки-распаковки и проверяемые преобразования типов (пра­вильность соответствия типов уже проверена компилятором), чтотакже повышает эффективность по сравнению с универсальнымтипом.Теперь рассмотрим реализацию обобщенного типа на Java:Stack<Integer> s = new Stack<Integer> (32);int [] x = {1,2,3,4,5,6,7} ;for (int k : x) s.Push(k);while (!s .IsEmpty()) System.out.println (s.Pop ());Stack <Double> sd = new Stack<Double> (12);double [] xx = {1.1,2.2,3.3,4.4,5.5,6.6,7.7};for (double k : xx) sd.Push(k);while (!sd.IsEmpty()) System.out.println(sd.Pop());По сравнению с предыдущим вариантом имеем два важных из­менения.Во-первых, в стеке хранятся ссылки типа Object (как в универ­сальном типе Stack), а не объекты типа параметра т, как в С#.

Этосвязано с тем, что в Java нельзя создавать массивы объектов типапараметра, как нельзя создавать и объекты типа параметра (new Т ()запрещено) внутри обобщенного класса.166Во-вторых, вместо Stack<int> (Stack<double>) используетсяStack<Integer> (Stack<Double>). Это связано с тем, что аргумен­тами конкретизаций могут быть только ссылочные типы, поэтомунеобходимо пользоваться классами-обертками.Эти ограничения продиктованы уже упоминавшимся в подразд.

10.1 обстоятельством: компилятор Java не сохраняет информа­цию о конкретизированных типах в программе (она используетсятолько на этапе трансляции). В отличие от С#, где для каждой раз­новидности типа генерируется свой набор функций-членов, в Javaиспользуется только код, сгенерированный по объявлению обобщен­ного типа. В объявлении никакой информации о типе нет, поэтомукод функций членов генерируется, как для ссылок на тип Object.Более того, обобщенный тип стек можно использовать и как обыч­ный универсальный тип (хотя делать это настоятельно не рекомен­дуется). В нашем случае универсальный тип Stack (см.

пример егоиспользования под разд. 7.1) будет прекрасно без всяких измененийработать и с обобщенным типом Stack.Зачем же тогда обобщенные типы в Java? Как и в С#, для надеж­ности: использование параметризованных контейнеров позволяетгарантировать, что они хранят объекты требуемого типа и не воз­буждают исключения, связанные с неверными преобразованиями.Очевидно, что повышенная безопасность — это основная цель до­бавления в язык механизма обобщений.Основной принцип современного индустриального программиро­вания заключается в том, что безопасность важнее эффективности.Рассмотрим еще одну конструкцию, связанную с обобщениями, —ограничения.Зададимся вопросом, что компилятору необходимо знать о типепараметре, чтобы скомпилировать объявления обобщенного типа.В языке C# необходимо знать, является ли тип типом значений,и если является, то каков его размер.

Про остальные типы известно,что это ссылки. Данной информации компиляторам Java и C# до­статочно, чтобы скомпилировать объявления, в которых значениятипа-параметра только присваиваются и передаются как параметр(строго говоря, можно вызывать операции для класса Object, по­скольку каждый тип гарантированно их поддерживает).Однако ни про какие другие операции компилятор ничего незнает. Поэтому вызов «нестандартных» операций изнутри обобщенийприводит к выдаче ошибки, т. е. компилятор не знает, поддержива­ется ли эта операция, поэтому и выдает ошибку, ведь гарантироватьправильность вызова операции нельзя.Ограничение — это конструкция, сообщающая компиляторуо том, что тип параметра поддерживает некоторые специфичные опе­рации, которые можно применять к значениям этого типа.

В моментконкретизации компилятор проверит, правилен ли тип-аргумент, т. е.поддерживает ли он перечисленные в ограничении операции.167Как сообщить о наличии у типа некоторых операций, отличныхот операций над Ob j ect, и откуда вообще берутся такие операции?Конечно же, новые операции появляются в языках C# и Java приобъявлении производного класса (от Object или от другого типа),когда программист определяет эти операции в объявлении класса.Других способов определения новых операций нет.

Вот и решениепроблемы: сообщить компилятору о том, что тип-параметр долженсовпадать или быть производным от типа, где определяется этаоперация.В C# синтаксис ограничений следующий:where список-ограниченийОграничение появляется после имени обобщенного класса. Огра­ничение может быть:• требованием наследоваться от определенного класса BaseClass(Т whereТ :BaseClass);• требованием быть типом значений (where Т: struct);• требованием иметь доступный конструктор умолчания (whereТ : new).Например:class Gen <Т,Х> where Trstruct, IComparable, X:new(){ ... }В Java допускается только требование наследования от определен­ного типа (Т extends BaseClass), поэтому ограничение ставитсявнутри списка параметров:class Gen <Т extends Comparable, X > { ...

}Рассмотрим пример контейнера, про элементы которого пред­полагается, что они являются производными от некоторого классаGood, содержащего операцию int getPrice (). Это необходимодля реализации операции вычисления суммарной цены всех элемен­тов контейнера. Конечно, можно описать контейнер в следующемвиде:class Container <Т extends Good>{int getOverallPrice (){. . .

T x; ... x .getPrice (); // корректно}}Однако такое решение не универсально, поскольку от любогопользователя контейнера требуется обязательно наследовать откласса Good, что слишком ограничительно (может мне ничего боль­ше и не надо кроме контейнера, а мне подсовывают еще и класс168в нагрузку). Лучшее решение (и самое общее) — ввести интерфейс,декларирующий метод getPrice (), и использовать его:interface IPricedltem{int getPrice ();}class Container <T extends IPricedItem>{int getOverallPrice(){. .

. T x;... x .getPrice (); // корректно}}Теперь любой класс, реализовавший интерфейс IPricedltem,может использовать обобщенный контейнер.Теперь рассмотрим пример контейнера, использующего упоря­дочение элементов. Чтобы сделать его максимально общим, следуетиспользовать стандартный интерфейс IComp а г able:class MyDict <Т> where Т: IComparable{// теперь можно использовать операцию сравнения// элементов контейнера: CompareTo(Object х)}Еще лучше использовать обобщенный стандартный интерфейс(для каждого подобного универсального класса и интерфейса суще­ствует обобщенный вариант):class MyDict <Т> where Т: IComparable<T>{// теперь можно использовать операцию сравнения// элементов контейнера: int CompareTo (Т х)}MyDict<String> stringDict = new MyDict<String> ();// корректно: строки поддерживают сравнениеMyDict<int> intDict = new MyDict<int> ();// тоже корректно: целые поддерживают сравнениеMyDict<Object> intDict = new MyDict< Object >();// ошибка компиляции — объекты в общем случае нельзя// сравниватьЯсно, что главная цель введения ограничений — повышение на­дежности обобщенных классов и методов..

Характеристики

Тип файла
PDF-файл
Размер
3,27 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6374
Авторов
на СтудИзбе
309
Средний доход
с одного платного файла
Обучение Подробнее