Предложения export
Предложение export
определяет псевдонимы для выбранных членов объекта.
Например:
class BitMap
class InkJet
class Printer:
type PrinterType
def print(bits: BitMap): Unit = println("Printer.print()")
def status: List[String] = ???
class Scanner:
def scan(): BitMap =
println("Scanner.scan()")
BitMap()
def status: List[String] = ???
class Copier:
private val printUnit = new Printer { type PrinterType = InkJet }
private val scanUnit = new Scanner
export scanUnit.scan
export printUnit.{status as _, *}
def status: List[String] = printUnit.status ++ scanUnit.status
Два пункта export
определяют следующие псевдонимы экспорта в классе Copier
:
final def scan(): BitMap = scanUnit.scan()
final def print(bits: BitMap): Unit = printUnit.print(bits)
final type PrinterType = printUnit.PrinterType
Доступ к ним возможен как изнутри Copier
, так и снаружи:
val copier = new Copier
copier.print(copier.scan())
// Scanner.scan()
// Printer.print()
Предложение export
имеет тот же формат, что и предложение импорта. Его общая форма:
export path . { sel_1, ..., sel_n }
Оно состоит из выражения квалификатора path
, которое должно быть стабильным идентификатором
и за которым следует один или несколько селекторов sel_i
, определяющих, что получает псевдоним.
Селекторы могут быть одной из следующих форм:
- Простой селектор
x
создает псевдонимы для всех подходящих членовpath
с именемx
. - Селектор переименования
x as y
создает псевдонимы для всех подходящих членовpath
, которым присвоено имяx
, но псевдониму присваивается имяy
вместоx
. - Пропускающий селектор
x as _
предотвращает создание псевдонимаx
. - Given селектор
given x
содержит необязательную привязку к типуx
. Он создает псевдонимы для всех подходящих экземпляровgiven
, которые соответствуют либоx
, либоAny
еслиx
опущен, за исключением членов, которые названы предыдущим простым селектором, переименованием или пропуском. - Селектор с подстановочным знаком
*
создает псевдонимы для всех подходящих членовpath
, за исключением экземпляровgiven
, синтетических элементов, созданных компилятором, и тех членов, которые названы предыдущим простым селектором, переименованием или пропуском. Замечания:
- также включены подходящие прокси-конструкторы, даже если они являются синтетическими членами.
- элементы, созданные
export
, также включаются. Они создаются компилятором, но не считаются синтетическими.
Элемент имеет право на export
, если выполняются все следующие условия:
- его владелец не является базовым классом класса (объекта или trait-а), содержащего предложение
export
, - элемент не переопределяет конкретное определение,
владельцем которого является базовый класс класса, содержащего предложение
export
. - он доступен в разделе
export
, - это не конструктор и не часть (синтетического) класса объекта,
- это given экземпляр (объявленный с помощью given) тогда и только тогда, когда экспорт осуществляется из given селектора.
Возникает ошибка времени компиляции, если простой селектор или селектор переименования не идентифицирует какие-либо подходящие элементы.
Члены типа получают псевдонимы в соответствии с определениями типов,
а члены-термины - в соответствии с определениями методов.
Псевдонимы экспорта копируют параметры типа и значения элементов, на которые они ссылаются.
Псевдонимы экспорта всегда final
.
Псевдонимы given экземпляров снова определяются как given.
Псевдонимы расширений снова определяются как расширения.
Псевдонимы встроенных методов или значений снова определяются как inline
.
Других модификаторов, которые можно присвоить псевдониму, нет.
Это имеет следующие последствия для переопределения:
- Псевдонимы экспорта нельзя переопределить, поскольку они являются
final
. - Псевдонимы экспорта не могут переопределять конкретные члены в базовых классах, поскольку они не помечены
override
. - Однако псевдонимы экспорта могут реализовывать отложенные члены базовых классов.
Псевдонимы экспорта для определений общедоступных значений, доступ к которым осуществляется без ссылки на private значения в пути к квалификатору, помечаются компилятором как "стабильные", а их типы результатов являются одноэлементными типами определений с псевдонимами. Это означает, что их можно использовать как часть путей стабильных идентификаторов, хотя технически они являются методами. Например, следующее допустимо:
class C { type T }
object O { val c: C = ... }
export O.c
def f: c.T = ...
Ограничения:
- Предложения экспорта могут появляться в классах или на верхнем уровне. Предложение экспорта не может появиться как оператор в блоке.
- Если предложение экспорта содержит подстановочный знак или селектор given,
его квалификатору
path
запрещается ссылаться на пакет. Это связано с тем, что еще неизвестно, как безопасно отслеживать зависимости по шаблону от пакета для целей инкрементной компиляции. - Переименование экспорта скрывает непереименованные экспорты, соответствующие целевому имени.
Например, следующее предложение будет недействительным, поскольку
B
скрыто переименованиемA as B
.export {A as B, B} // error: B уже скрыто
- Переименования в предложении экспорта должны иметь попарно разные целевые имена.
Например, следующий пункт будет недействительным:
export {A as C, B as C} // error: дублированное переименование
- Простое переименование экспорта, например
export status as stat
пока не поддерживаются. Оно нарушило бы ограничение, что экспортируемый объект не может быть уже членом объекта, содержащего экспорт. Это ограничение может быть снято в будущем.
Ссылки: