Перейти к основному содержимому

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В заключении укажем еще два важных момента, которые характерны для типа неизвестно:

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