Однократные функции, закрепление и универсальность
Однократные функции, закрепление и универсальность
В этом разделе мы обсудим конкретную техническую проблему, поэтому при первом чтении книги его можно пропустить.
Однократные функции, тип которых не является встроенным, вносят потенциальную несовместимость с механизмом закрепления типов и универсальностью.
Начнем с универсальности. Пусть в родовом классе EXAMPLE [G] есть однократная функция, чей тип родовой параметр:
f: G is once ... end
Рассмотрим пример ее использования:
character_example: EXAMPLE [CHARACTER]
...
print (character_example.f)
Пока все в порядке. Но если попытаться получить константу с другим родовым параметром:
integer_example: EXAMPLE [INTEGER]
...
print (integer_example.f + 1)
В последней инструкции мы складываем два числа. Первое значение, результат вызова f, к сожалению, уже найдено, поскольку f - однократная функция, причем символьного, а не числового типа. Сложение окажется недопустимым.
Проблема заключается в попытке разделения значения разными формами родового порождения, ожидающими значения, тип которого определяется родовым параметром. Аналогичная ситуация возникает и с закреплением типов. Представим себе класс B, добавляющий еще один атрибут к компонентам своего родителя A:
class B inherit A feature
attribute_of_B: INTEGER
end
Пусть A имеет однократную функцию f, возвращающую результат закрепленного типа:
f: like Current is once create Result make end
и пусть первый вызов функции f имеет вид:
a2 := a1.f
где a1 и a2 имеют тип A. Вычисление f создаст экземпляр A и присоединит его к сущности a2. Все прекрасно. Но предположим, далее следует:
b2 := b1.f
где b1 и b2 имеют тип B. Не будь f однократной функцией, никакой проблемы бы не возникло. Вызов f породил бы экземпляр класса B и вернул его в качестве результата. Но функция является однократной, а ее результат был уже найден при первом вызове. И это - экземпляр A, но не B. Поэтому инструкция вида:
print (b2.attribute_of_B)
попытается обратиться к несуществующему полю объекта A.
Проблема в том, что закрепление вызывает неявное переопределение типов. Если бы f была переопределена явно, с применением в классе B объявления
f: B is once create Resultl make end
при условии, что исходный вариант f в классе A возвращает результат типа A (а не like Current), все было бы замечательно: экземпляры A обращались бы к версии f для A, экземпляры B - к версии f для B. Однако закрепление типов было введено как раз для того, чтобы избавить нас от таких явных переопределений.
Эти примеры - свидетельства несовместимости семантики однократных функций (с процедурами все прекрасно) с результатами применения закрепленных типов и формальных родовых параметров. Одно из решений проблемы в том, чтобы трактовать такие случаи как явные переопределения, приняв за правило то, что результат однократной функции совместно используется лишь в пределах одной формы родовой порождения, а при закреплении результата - лишь среди экземпляров своего класса. Недостатком такого подхода, впрочем, является, что он не отвечает интуитивной семантике однократных функций, которые, с позиции клиента, должны быть эквивалентны разделяемым атрибутам. Во избежание недоразумений и возможных ошибок можно пойти на более суровые меры, наложив полный запрет на сценарии подобного рода:
Правило для однократной функции
Тип результата однократной функции не может быть закреплен и не может включать любой родовой параметр.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Универсальность
Универсальность Для современных серверов стандарты Ц—П устанавливает индустрия ПК. Серверы на процессорах Intel с Windows NT задали планку, которой приходится соответствовать всем остальным. Пока Ц—П серверов AS/400 весьма конкурентоспособна. Однако планка не фиксирована, она
1.4.1. Задание на закрепление материала
1.4.1. Задание на закрепление материала Задание 1.1. Начертите схему электрической цепи из последовательно соединенных резистора, катушки индуктивности и конденсатора, изображенную на рис. 1.21. Сохраните свой чертеж в папке Projects под именем RLC_MIX1.sch. Рис. 1.21. Схема цепи из
3.1.1. Задания на закрепление материала
3.1.1. Задания на закрепление материала Задание 3.1. Подумайте, к чему относится угол фазы конденсатора -68.3°, установленный программой PSPICE: к общему напряжению или, как это часто бывает в электротехнике, к току в цепи последовательного включения конденсатора и
4.4.1. Задания на закрепление материала
4.4.1. Задания на закрепление материала Задание 4.1. Создайте диаграмму входного и выходного напряжения для электросхемы RC_TRANS.sch в сокращенном временном интервале от 0 с до 1 мс. Задание 4.2. Уменьшите ширину шага вычислений (поле Step Ceiling) для моделирования электросхемы RC_TRANS.sch
6.6.3. Задание на закрепление материала
6.6.3. Задание на закрепление материала Задание 6.4. Загрузите на экран редактора SCHEMATICS схему последовательной цепи RLC.sch (рис. 6.1) и проведите для нее анализ AC Sweep в диапазоне частот 100 Гц–1 МГц. По окончании моделирования выведите на экран PROBE диаграмму частотных характеристик
Закрепление областей
Закрепление областей Предположим, что вы работаете с большой таблицей. В процессе работы вам приходится часто использовать полосы прокрутки, чтобы ввести данные в различные ячейки. При этом заголовки столбцов (самые различные, например: Товар, Цена, Количество,
Универсальность (genericity)
Универсальность (genericity) Для того чтобы типизация была практичной, необходимо иметь возможность определять классы с параметрами, задающими тип. Такие классы известны как родовые. Родовой класс LIST [G] описывает списки элементов произвольного типа G - "формальным родовым
Перегрузка и универсальность
Перегрузка и универсальность Два технических приема - перегрузка (overloading) и универсальность (genericity) предлагают свои решения, направленные на достижение большей гибкости описанных выше механизмов. Рассмотрим, что же они могут дать.
Универсальность (genericity)
Универсальность (genericity) Универсальность - это механизм определения параметризованных шаблонов модулей (module patterns), параметры которых представляют собой типы. Это средство является прямым ответом на требование Изменчивости Типов. Оно устраняет необходимость
Ограниченная универсальность
Ограниченная универсальность Расширяя базовое понятие класса, мы представляли наследование и универсальность (genericity) как своего рода "партнеров". Объединить их нам позволило знакомство с полиморфными структурами данных: в контейнер - объект, описанный сущностью типа
Однократные функции
Однократные функции Пусть константный объект - это функция. Например, i можно (в иллюстративных целях) описать внутри самого класса COMPLEX какi: COMPLEX is-- Комплексное число, re= 0, а im= 1docreate Result.make_cartesian (0, 1)endЭто почти решает нашу задачу, поскольку функция всегда возвратит ссылку на
Однократные процедуры
Однократные процедуры Функция close должна вызываться только один раз. Контроль над количеством ее вызовов рекомендуется возложить на глобальную переменную приложения. Из руководства к коммерческой библиотеке функций языка C Механизм однократных функций интересен и
У18.2 Однократные функции для эмуляции unique-значений
У18.2 Однократные функции для эмуляции unique-значений Покажите, что в языке без поддержки unique-объявлений результат, аналогичныйvalue: INTEGER is uniqueможно получить, воспользовавшись объявлением видаvalue: INTEGER is once...endгде вам необходимо написать тело однократной функции и все, что
У18.3 Однократные функции в родовых классах
У18.3 Однократные функции в родовых классах Приведите пример однократной функции, чей результат включает родовой параметр, и, если он не корректен, порождает ошибку времени
У18.4 Однократные атрибуты?
У18.4 Однократные атрибуты? Исследуйте полезность понятия "однократного атрибута", полученного по образцу однократной функции? Будет ли такой атрибут общим для всех экземпляров класса? Как инициализировать однократные атрибуты? Являются ли они избыточными при наличии