Smalltalk в примерах/Глобальные переменные

Я начну со стандартного предупреждения о том что глобальные переменные должны использоваться редко, если вообще использоваться, и поэтому большинство информацыи должно храниться в переменных экзэмпляра или передаваться как аргументы метода. Учитывая выше сказанное, глобальная информация и объекты используются определённым образом. Ты можешь использовать константы которые часто используются твоей системой, или ты можешь использовать глобальные объекты например объекты конфигурации или trace log object. Давай рассмотрим несколько техник которые могут использоваться для данной цели. Мы будем использовать два примера: конфигурационный объект и время простоя.


Глобальный словарьПравить

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

Smalltalk от: #Timeout поместить: 20.
Smalltalk от: #Конфигурация поместить: МояКонфигурация новый.

Я не рекомендую использовать Smalltalk для глобальных переменных программы из за того что его очень интенсивно использует система Smalltalk (например, он содержит все классы системы, и глобальные переменные такие как Транскрипт, Процессор, и ScheduledControllers). Я предпочитаю не загромождать Smalltalk объектами программы из за риска конфликта имён.

Pool словарейПравить

Следующая техника это использование PoolСловаря. PoolСловарь содержит объекты к которым ты хочешь иметь глобальный доступ в твоей программе. Хорошая особенность PoolСловаря это то что класс должэн зарегистрировать свой интерес к нему до его использования, таким образом тебе можно точно amount of scoping. Способ которым класс регистрирует свой интерес это имя PoolСловаря в соответствующей строке в определении класса. (---) В следующем примере, я назвал его МойPoolСловарь.


ИмяСуперкласса подкласс: #ИмяКласса
  именаПеременныхЭкзэмпляра: 'имяПерЭкз1 имяПерЭкз2'
  именаПеременныхКласса: 'ИмяПерКласса1 ИмяПерКласса2'
  poolСловари: 'МойPoolСловарь'
  категория: 'MyStuff'

До того как ты напишешь код ты должен сделать две вещи. Первое, до того как ссылаться на PoolСловарь в твоём определении класса тебе надо сделать имя PoolСловаря универсально известным путём его помещения в словарь Smalltalk. Чтобы сделать это выполни следующую строку. Заметь что мы используем Словарь а не IdentityСловарь. Потому что из за способа реализацыи IdentityСловаря он не работает как PoolСловарь.


Smalltalk от: #МойPoolСловарь поместить: Словарь новый.

До того как ты напишэш код ссылающийся на объект в PoolСловаре, ты добавляеш этот объект в него для того чтобы компилятор мог связать имя переменной в твоём методе с объектом в PoolСловаре. Однако, компилятор нуждается только в ссылке на имя в PoolСловаре и не заботится о типе объекта. Чтобы сохранить твой метод, простейшым способом будет сказать вначале:


МойPoolСловарь от: #Конфигурацыя поместить: ноль.

Ты не должэн выполнять эти шаги вручную каждый раз когда ты file in твой код (\potom). Таким образом, при начинании файла \potom


Smalltalk от: #МойPoolСловарь поместить: Словарь новый.
МойPoolСловарь от: #Конфигурацыя поместить: ноль.

Если у тебя есть код который обращается к переменным PoolСловаря и ты создаёш новый PoolСловарь, код не сможэт большэ находить старые переменные. \potom


Browser browseAHCallsOn: (MyPoolDictionary associationAt: #Config).


ComposedTextView openSystemWorkspace.


Переменные стороны классаПравить

Следующая техника используется для хранения глобальных данных. Например, ты можэш иметь два класса: \emph{МоиГлобальныеДанные} и \emph{МоиКонстанты}. Глобальные и константные переменные доступны при помощи посылки сообщений соответствующему классу. Например, ты можэш определить и обратиться к величине простой следующим образом.


МойКласс>>мойМетод
  простой := МоиКонстанты простой.
  ...
класс МоиКонстанты>>простой
  ^20

Можно сослаться на глобальное значение и инициализировать (в данной случае файл журнала) как показано ниже.


МойКласс>>мойМетод
  ...
  МоиГлобальныеДанные журнал запись: 'зарплата=',
                             зарплата строкаДляПечати.
класс МоиГлобальныеДанные>>журнал
  ^журнал
класс МоиГлобальныеДанные>>иницыализацыя
  журнал := МойЖурнал on: сам имяЖурнала.

Для нахождения всех ссылок на индивидуальные глобальные переменные, ты можэш просмотреть ссылки на сообщения которые возвращают глобальные переменные. Чтобы просмотреть места где используются глобальные переменные, ты можэш просмотреть ссылки на класс \emph{МоиГлобальныеДанные}. Аналогично, для констант.


В отличии от переменных в PoolСловаре, ты не должэн делать что-либо on fileIn, и ты не можэш быть уверенным что ссылка содержыт объект когда ты пишэш метод который ссылается на константу или глобальную переменную. \potom.


Default instancesПравить

\potom


MyClass class>>initialize
"self initialize"
  Default := self new.


MyClass class»default
 ^ Default


length := MyClass default length.


length := MyClass length.


MyClass class»doesNotUnderstand: aMessage
 ^self default
   perform: aMessage selector
   withArguments: aMessage arguments


Переменные окружения / Аргументы командной строкиПравить

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


CEnviroment команднаяСтрока.

Ты такжэ можэш извлечь переменную окружэния используя \verb|getenv:|. Например,


CEnviroment getenv: 'LOGNAME'

\section{Номер версии образа}

Номер версии образа можэт быть получен двумя способами. Ты можэш послать сообщение \verb|версия| Smalltalk'у, или \verb|versionId| ObjectMemory. Например, в VW 2.0, я поступаю так.


Smalltalk версия 'VisualWork(R) Release 2.0 of 4 August 1994'
ObjectMemory versionId  #[42 26 35 0 20 0 0 4 42 26 35 4].

В частности, элемент 5 возвращаемого \verb|versionId| массива это основной номер версии образа. VW 2.0 выдаёт 20, а VW 2.5 выдаёт 25. Т.е. чтобы определить что ты используеш VW 2.0 ты можэш выполнить любую следующую строку.


(Smalltalk version findString: '2.0' startingAt: 1) > 0
(ObjectMemory versionId at: 5) == 20

Управляющие структуры →