Функциональные типы

Функциональный тип — это тип, значениями которого являются методы. Функциональные типы позволяют хранить методы в переменных, передавать их в другие методы как аргументы и возвращать как результат.

Имя функционального типа содержит типы параметров и возвращаемого значения, разделенные символом лямбда-операции -> (подробнее).

Например, функциональный тип, значением которого является метод, принимающий два параметра типа Число и возвращающий значение типа Строка:
(Число, Число)->Строка

Значение функционального типа может быть записано двумя способами:

Имя типа

Имя функционального типа содержит типы параметров и возвращаемого значения, разделенные символом лямбда-операции ->. Например:

  • Значением типа является метод с одним параметром типа Число, возвращающий значение типа Число
    знч Результат: (Число)->Число = ...
  • Значением типа является метод с двумя параметрами типа Число, возвращающий значение типа Булево
    знч Результат: (Число, Число)->Булево = ...
  • Значением типа является метод с двумя параметрами типа Число, возвращающий значение составного типа (Строка или Неопределено)
    знч Результат: (Число, Число)->Строка? = ...
  • Значением типа является метод с одним параметром составного типа (Число или Неопределено),возвращающий значение составного типа (Строка или Число)
    знч Результат: (Число?)->Строка|Число = ...
  • Значением типа является метод без параметров, возвращающий значение типа Строка
    знч Результат: ()->Строка = ...
  • Значением типа является метод с одним параметром типа Строка, не возвращающий ничего
    знч Результат: (Строка)->ничто = ...
    Примечание:
    • ничто никуда нельзя присвоить и с ним никак нельзя взаимодействовать;
    • Значение типа (XXX)->YYY можно присвоить в переменную типа (XXX)->ничто.
  • Составной тип, значением которого является либо Неопределено, либо метод с одним параметром типа Число, возвращающий значение типа Строка
    знч Результат: ((Число)->Строка)? = ...
  • Составной тип, значением которого является либо Булево, метод с одним параметром типа Число, возвращающий значение типа Строка
    знч Результат: ((Число)->Строка)|Булево = ...
    Примечание:

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

  • Если в качестве типа переменной указано неизвестно, то проверка типов компилятора отключается и такое значение можно вызывать с любым количеством параметров. Будет ошибка или нет станет ясно только во время работы приложения:
    пер МойМетод: неизвестно
    МойМетод(Истина, 44) // ошибки компиляции нет

В общем виде имя функционального типа выглядит следующим образом:

(тип-параметра-1, ..., тип-параметра-n)->тип-результата

где:

  • тип-параметра-1, ..., тип-параметра-N — типы параметров, если они есть;
  • -> — лямбда-операция;
  • тип-результата — тип возвращаемого значения.

Вызов значения функционального типа

Синтаксически выглядит как вызов обычного метода:

[выражение.]имя([аргументы])

например:

МойМетод()
Фильтровать(7)
Товар.Категория.Добавить("Принтер")

При этом действует следующий приоритет разрешения имен:

  • Если существует метод с указанным именем (любого приоритета), то считается, что это вызов метода;
  • Иначе ищем свойство с указанным именем в порядке приоритетов и считаем это вызовом функционального типа.

Иерархия типов и вариантность

Значения функциональных типов обеспечивают ковариантность по возвращаемым типам и контравариантность по типам параметров.

Ковариантность по возвращаемым типам

Метод, возвращающий значение производного типа можно присвоить в метод, возвращающий значение базового типа:

пер п1: (Строка)->Объект   // Базовый
пер п2: (Строка)->Число    // Производный от Объект
п1 = п2   // Ok

Метод, возвращающий значение простого типа можно присвоить в метод, возвращающий значение составного типа, в который входит этот простой тип:

пер п1: (Строка)->Число|Строка   // Составной
пер п2: (Строка)->Число          // Входит в составной
п1 = п2   // Ok
Контравариантность по типам параметров

Метод с параметром базового типа можно присвоить в метод с параметром производного типа:

пер п1: (Число)->Строка    // Производный от Объект
пер п2: (Объект)->Строка   // Базовый
п1 = п2    // Ok

Метод с параметром составного типа можно присвоить в метод с параметром простого типа, который входит в этот составной тип:

пер п1: (Число)->Строка          // Входит в составной
пер п2: (Число|Булево)->Строка   // Составной
п1 = п2   // Ok

Присваивания в другую сторону неверны.