Модульная загадка про константу
Рассмотрим модульную расширяемую систему. Создадим первый модуль, в котором определим константу, и скомпилируем его. Создадим второй модуль, который импортирует первый модуль и использует определённую ранее константу. Скомпилируем второй модуль. А теперь возьмем первый модуль, изменим в нем значение константы на другое и скомпилируем его. Второй модуль перекомпилировать не будем. Запустим на выполнение старый второй модуль вместе с новым первым. Что произойдет? Что реально происходит в таких модульных расширяемых системах как Oberon и .NET я сообщу позже, а сейчас давайте подумаем что должно происходить. Идеальным было бы так, чтобы второй модуль использовал новое значение константы из первого модуля. Не так ли? Что этому мешает? Я думаю, что как минимум на это есть две причины. Во-первых, при компиляции второго модуля константа могла быть нужна компилятору, например, для определения размера переменных в том случае если бы она была использована, например, как размер (не динамического) массива. Во-вторых, используя константу вместо переменной компилятор может осуществить оптимизацию. Первая причина в отличие от второй является фатальной. Выходит, мы не можем ожидать от второго модуля использование константы из первого модуля? Но, не кажется ли Вам, что это какой-то бред? Второй модуль использует константу из первого модуля, которую использовать не может — точно бред, не так ли? Выходит в модульных расширяемых системах просто напросто должно быть запрещено экспортирование / имортирование констант! Ибо это просто невозможно физически реализовать.
Что реально происходит в Oberon (BlackBox 1.5 BETA):
MODULE Module1;
CONST N* = 10; (* Потом меняем ее на 20 *)
END Module1.
MODULE Module2;
IMPORT StdLog, Module1;
PROCEDURE Do*;
BEGIN
IF Module1.N = 10 THEN
StdLog.String("Module1.N = 10"); StdLog.Ln
ELSE
StdLog.String("Module1.N # 10"); StdLog.Ln
END
END Do;
END Module2.
При попытке запустить на выполнение старого второго модуля с новым первым происходит ошибка:
"command error: object Module1.N inconsistently imported from Module2"
Что реально происходит в .NET (1.1)
namespace Test
{
public sealed class Module1
{
public const int N = 10; /* Потом меняем ее на 20 */
}
}
namespace Test
{
class Program
{
static void Main(string[] args)
{
if(Module1.N == 10)
{
System.Console.WriteLine("Module1.N = 10");
}
else
{
System.Console.WriteLine("Module1.N # 10");
}
System.Console.ReadLine();
}
}
}
Запускаем на выполнение старый второй модуль с новым первым, в консоли преспокойно печатается какая-то ерунда:
"Module1.N = 10"
ведь в новом первом модуле Module1.N = 20. Совсем не ожиданно, однако...