Моделирование обобщенных (generic) типов с помощью абстрактных типов
Наличие двух абстракций типов в одном языке поднимает вопрос о сложности языка - нельзя ли было обойтись одной? В этом разделе мы покажем, что функциональная абстракция типов (ака обобщенные типы) может в принципе быть смоделирована с помощью объектно-ориентированной абстракции типов (иначе абстрактных типов). Одну форму можно трансформировать в другую. Идея трансформации в общих чертах описана ниже.
Предположим, что у нас есть параметризованный класс C с параметром типа Т (код напрямую обобщается в множественные параметры типов). Трансформация состоит из четырех частей, затрагивающих определение класса, создание экземпляров класса, вызовы конструкторов базового класса и экземпляры типов класса.
1. Определение класса C трансформируется так:class C
{
type t;
/* остальная часть класса */
}
Таким образом, параметры исходного класса моделируются с помощью абстрактных членов трансформированного класса. Если параметр типа t имеет сужения и/или расширения, они переносятся в определение абстрактного типа. Вариантность параметров типа не переносится; вместо этого вариантность влияет на формирование типов (см. пункт 4).
2. Создание каждого экземпляра new C[T] с аргументом типа Т трансформируется в:new C { type t = T }
3. Если C[T] выступает в роли конструктора суперкласса, его классы-наследники дополняются определением:type t = T
4. Каждый из типов C[T] трансформируется в один из следующих типов, каждый из которых дополняет класс С уточнением:
C { type t = T } если t объявлен не вариантным,
C { type t <: T } если t объявлен ковариантным,
C { type t >: T } если t объявлен контрвариантным.
Такой код работает, если не встречается конфликтов имен. Поскольку имя параметра становится членом класса, оно может конфликтовать с другими членами, включая унаследованные члены, сгенерированные по именам параметров базовых классов. Этих конфликтов имен можно избежать переименованием, например, дополнением каждого имени уникальным номером.
Возможность трансформации из одного стиля абстракции в другой полезна, так как снижает концептуальную сложность языка. В случае Scala обобщенные типы становятся не более, чем "синтаксическим сахаром", который можно устранить трансформацией в абстрактные типы. Однако возникает вопрос, насколько обосновано наличие этого синтаксического сахара, и нельзя ли обойтись одними абстрактными типами, то есть ограничиться синтаксически меньшим языком. Есть два аргумента за включение обобщенных типов в Scala. Во-первых, трансформацию в абстрактные типы не так уж просто писать вручную. Это приводит потерь выразительности, и есть также проблема случайных конфликтов имен между именами абстрактных типов, эмулирующих параметры типов. Во-вторых, обобщенные и абстрактные типы обычно играют в Scala-программах различные роли. Обобщенные типы обычно используют, когда нужна только реализация экземпляра типа, а абстрактные типы - когда нужна ссылка на абстрактный тип из клиентского кода. Последнее встречается, в частности, в двух ситуациях. Может понадобиться спрятать точное определение члена типа от клиентского кода, чтобы получить нечто вроде инкапсуляции, известной по модульным системам в SML-стиле. Или же может потребоваться переопределить тип ковариантно в подклассах, чтобы получить семейный полиморфизм.
Можно ли пойти другим путем и перекодировать абстрактные типы в обобщенные? Оказывается, это значительно труднее, и требует полного переписывания программы. Это было показано в исследованиях в области модульных систем, где доступны оба вида абстракции [21]. На самом деле такая сложность неудивительна, если рассматривать проблему с точки зрения основ теории типов обеих систем. Обобщенные типы (без F-ограничений) могут выражаться в System F<: [описанной в 9], тогда как абстрактные типы требуют системы, основанной на зависимых типах. Последние, в общем, выразительнее предыдущих, например, ?Obj с его зависимыми от пути типами позволяет закодировать F<:.
- Введение
- История
- Истоки дизайна
- Ключевые аспекты языка
- Объектно-ориентированный язык
- Функциональный язык
- Java-подобный язык
- Классы
- Операции
- Переменные и свойства
- Операции - это объекты
- Методы и функциональные значения
- Функции - это объекты
- Последовательности
- For Comprehensions
- Абстракции
- Функциональная абстракция
- Вариантность (Variance).
- Абстрактные члены
- Семейный полиморфизм (family polymorphism) и self-типы.
- Моделирование обобщенных (generic) типов с помощью абстрактных типов
- Композиция
- Повторное использование классов
- Наследование.
- Trait
- Декомпозиция
- Объектно-ориентированная декомпозиция
- Модель данных
- Автономные компоненты
- Адаптация компонентов
- Виды (views)
- 9.1.11. Система управління бізнесом і фінансами Scala
- 2. Структура и основные характеристики системы Scala
- 3. Система управління бізнесом і фінансами scala 5
- 14. 3. Система управління бізнесом і фінансами Scala 5
- Combining Scala and Java
- Next Steps in Scala
- 30.1 Equality in Scala
- The Scala Collections API
- 31.1 Using Scala from Java
- Scala Scripts on Unix and Windows