Тип «неизвестно»

В ряде случаев необходимо описать переменную, тип которой мы не знаем в момент написания приложения. При этом нам важно, чтобы это была конкретная переменная. От этой переменной можно вызывать какие-то методы, эта переменная может принимать участие в операциях и т. д. Но в случае языка с явной типизацией переменных, мы не можем просто описать переменную, не указывая ее типа.

В данной ситуации можно объявить переменную составного типа Объект?. Такой тип позволит присвоить нашей переменной абсолютно любое значение, т. к. тип Объект является базовым для любых других типов, кроме Неопределено. А суффикс "?" позволяет присваивать в нашу переменную и значение Неопределено. Но при таком описании переменной нам доступен только метод ПолучитьТип() и все. Это произойдет потому, что компилятор "знает" только об этом методе.

Чтобы решить эту проблему, существует тип неизвестно. Фактически, данный тип существует исключительно во время компиляции исходного текста программы. Его назначение: отключить проверку типов компилятора. Все проверки будут выполняться во время исполнения, когда станет ясно, значение какого типа размещено в переменной, объявленной с типом неизвестно.

Сказанное выше иллюстрирует пример:

метод Скрипт()
    область
        пер Значение: Объект?
        Значение = "Строка"
        Консоль.Записать(Значение.Длина())
    ;
    область
        пер Значение: неизвестно
        Значение = "Строка"
        Консоль.Записать(Значение.Длина())
    ;
;

Попытка выполнить данный пример (в приведенном виде) приведет к ошибке компиляции Вызовы неизвестного метода "Длина" в строке Консоль.Записать(Значение.Длина()) первой области. Если эту строку закомментировать, то пример выполнится успешно.

Когда можно применять данный тип?

Допустим у нас есть набор структур, который описывает файлы в файловой системе. Каждая структура содержит общий набор полей, например, имя файла и его тип. И для каждого типа файла есть специфический набор полей. При этом нам нужен метод, который будет принимать на вход любую из таких структур в качестве параметра и выполнять какие-то общие действия. В этом случае встает вопрос - каким образом типизировать параметр нашего метода? Можно рассмотреть вариант составного типа, но тогда при добавлении нового типа файла придется уточнить состав типов. Другим вариантом служит описание параметра метода с помощью типа неизвестно.

Такой тип позволит внутри метода обращаться к свойствам параметра, не "обращая внимания" на фактический тип полученной структуры. При этом во время компиляции ошибок возникать не будет, но контроль наличия свойств и методов все равно будет выполняться во время выполнения модуля.

структура ФайлИсполнимый
    пер ИмяФайла: Строка
    пер ТипФайла: Строка
    пер Архитектура: Число
;

структура ФайлТекстовый
    пер ИмяФайла: Строка
    пер ТипФайла: Строка
    пер Кодировка: Строка
;

структура ФайлКонфигурационный
    пер ИмяФайла: Строка
    пер ТипФайла: Строка
    пер Формат: Строка
;

метод Скрипт()
    пер Файл1 = новый ФайлИсполнимый("util.exe", "exe", 32)
    пер Файл2 = новый ФайлТекстовый("untitled.txt", "txt", "utf-8")
    пер Файл3 = новый ФайлКонфигурационный("default.vrd", "cfg", "xml")
    ВыполнитьДействие(Файл1)
    ВыполнитьДействие(Файл2)
    ВыполнитьДействие(Файл3)
;

метод ВыполнитьДействие(Параметр: неизвестно)
    пер Значение = Параметр.ТипФайла
    выбор Значение
    когда "exe"
        Консоль.Записать("Архитектура исполняемого файла = %{Параметр.Архитектура}")
    когда "txt"
        Консоль.Записать("Кодировка текстового файла = %{Параметр.Кодировка}")
    когда "cfg"
        Консоль.Записать("Формат конфигурационного файла = %{Параметр.Формат}")
    иначе
        Консоль.ЗаписатьОшибку("Неизвестный тип файла: " + Параметр.ТипФайла)
    ;
;

Компилятор не будет "возражать" против использования свойств от разных структур у одного параметра, т. к. параметр объявлен с типом неизвестно. Но если во время исполнения в качестве параметра будет передано что-то совсем неожиданное для метода - будет исключение времени выполнения.

В заключении укажем еще два важных момента, которые характерны для типа неизвестно:
  • Для такого типа не существует значения типа Тип. Выражение Тип(неизвестно) не будет пропущено компилятором.
  • Для типа неизвестно не существует значения.