prepod

Путь к Файлу: /РОССИЙСКИЙ НОВЫЙ УНИВЕРСИТЕТ / Smalltalk / Синтаксис.doc

Ознакомиться или скачать весь учебный материал данного пользователя
Скачиваний:   1
Пользователь:   prepod
Добавлен:   04.05.2015
Размер:   259.5 КБ
СКАЧАТЬ

Синтаксис

Синтаксис Smalltalk’а очень прост и состоит из литералов, переменных, сообщений и блоковых переменных.   Эта простота делает синтаксис Smalltalk’а простым для изучения. Соответствующая VisualWorks версия Smalltalk’а согласуется со стандартами ANSI для синтаксиса этого языка, но использует некоторые расширения. Описание синтаксиса в форме Бэкуса-Наура дается в Приложении А “Описание синтаксиса версии Smalltalk’а для VisualWorks”.

Литералы

Литерал – это выражение Smalltalk’а, которое всегда относится к одному и тому же объекту.  Это отношение не может быть изменено. В VisualWorks существуют различные виды литералов. И их число входят числа, буквы, строки, символы, массивы, байтовые массивы и три специальных литерала: nil, true и false. Заметим, что литералы строго типизированы, то есть они являются полнокровными объектами, экземплярами класса и отвечают на вопросы всего протокола своего класса.

Числа

Числа представлены обычным образом с использованием знака минус и десятичной запятой, если это необходимо.

Целые числа

Целые числа представлены как литералы из чисел, вроде 101 или результат арифметических операций с одним или большим числом чисел, вроде 55 + 46.

Числа с плавающей запятой

Числа с плавающей запятой должны иметь, по крайней мере, одно десятичное число слева от десятичной запятой (точки), чтобы компилятор мог отличить эту точку от точки, ограничивающей выражение.  Таким образом, выражение 0.005 принимается, а выражение .005 незаконно. В научной нотации e заменяется на d при задании двойной точности, а q – при четырехкратной.

Числа с фиксированной запятой (точкой)

Числа с фиксированной запятой полезны в случае применения к проблемам бизнеса, где эти числа изображаются путем помещения знаков после целых литералов или чисел с плавающей запятой. Число предшествующих десятичных знаков попросту определяет масштаб числа (число десятичных знаков, которые надо обеспечить) Заметим, что точный масштаб имеет преимущество перед неявным, так что 99.95s4 представляет собой то же, что 99.9500s, а 99.9500s2 – ошибка.

Недесятичные числа

Числовые литералы могут также быть выражены в недесятичной форме с начальным указанием основания системы счисления числа с помощью буквы r (от слова radix-корень). Например, когда основание больше десяти, то заглавные буквы, начинающиеся с “A”, используются для чисел, превышающих девять. Например, шестнадцатеричным эквивалентом десятичного числа 255 является 16rFF.

Числа в научной нотации

Числа могут быть выражены в научной нотации путем включения суффикса, составленного из e (для экспоненты) или d (для двойной точности) вместе с десятичной экспонентой. Заметьте, что Вы можете применить букву q вместо d. Это буква (q – учетверенная точность) применяется для переносимости в других системах языка Smalltalk, но в VisualWorks, q имеет то же значение, что и d. Основание возводится в степень, указанную в экспоненте, а умножается на приведенное число. Например:

Восьмеричное    Десятичное

          8r377                    255

                  8r34.1                   28.125

                  8r-37                    -31

     Scientific Notation   Decimal

                        1.586d5             158600.0

                        1586e-3             0.001586

Знаки

Литералам, обозначающим знаки, всегда предшествует знак доллара. Например,

$a

$M

$-

$$

$1

Строки

Строка–литерал заключена в одинарные кавычки (двойные кавычки используются, чтобы выделить комментарий). Любой символ в строку-литерал. Если в строку-литерал должна быть включена одинарная кавычка, то ей должна предшествовать тоже одинарная кавычка. Например:

            'I won''t fail'

Символы

Символ представляет собой ярлык, передающий название единственного объекта, например такое, как название класса. В системе имеется только один экземпляр каждого символа. Литералу символа предшествует знак номера, а сам символ может быть заключен в одинарные кавычки. Например,     #Float и #'5%' представляют собой действующие символы. Если символ представляет собой массив, ему все равно должен предшествовать знак номера.

Массивы байтов

Литерал, представляющий собой массив байтов, заключается в квадратные скобки, которым предшествует знак номера. Элементами массива должны быть целые числа от 0 до 255. Они разделяются одним или большим числом пробелов. Результатом служит экземпляр класса ByteArray, как и показано в следующем примере:

                             #[255 0 0 7]

Массивы

Массив литералов заключается в круглые скобки, и ему также предшествует знак номера. Элементы массива разделяются одним или более пробелами (лишние пробелы не учитываются). Массиву литералов, включенному в другой массив, также должен предшествовать знак номера. В следующем примере содержатся число, знак, строка, симвло и другой массив со знаком (состоящий из трех символов):

#(1586.01 $a 'sales tax' #January #($x $y $z))

Замечание: Когда Вы меняете элемент в неодиночных массивах постоянных (a String, an Array или в a ByteArray), это изменение отражается глобально. Учитывая это обстоятельство, опытные программисты на Smalltalk’е редко применяют изменяющиеся литералы-константы при переходе от одного метода к другому, а используют вместо этого копии.

Булевы выражения

Булева константа true является единственным экземпляром класса True, который является подклассом класса Boolean. Константа false – единственный экземпляр класса False, который также является подклассом класса Boolean. В отличие от большинства значения true и false жестко фиксированы в компиляторе, который рассматривает их только как постоянные. Однако, их поведение определяется в методах экземпляра в классах True и False. Они используются при выполнении логических операций, таких как not.

nil

Объект nil – единственный экземпляр класса UndefinedObject. Как и подразумевается названием класса, nil представляет собой нулевое значение, данное месту переменной, для которой еще  не определено более интересное значение.  Как и булевы выражения, nil не может изменяться в компиляторе. Ее поведение определено в UndefinedObject – например, она не выполняет метод isNil, введенный в класса Object (отвечая true вместо false). Предполагается, в системе имеется только один экземпляр nil. Не создавайте дополнительных экземпляров, даже если это возможно при использовании basicNew, так как может послужить причиной нарушений в VisualWorks.

Переменные

Объекты определяются по их названиям. Исключение допускается в случае литералов, когда объекты получают название по их переменным. Переменные в зависимости от области применения разделяются на два типа. Private (частные) переменные могут относиться только к отдельному объекту. Они являются частными именно для этого объекта. Shared (общие) переменные могут относиться ко множественным объектам.

Типы переменных

В отличие от некоторых других способов организации объектно-ориентированной среды, переменные Smalltalk’а не имеют типов в том смысле, что любая переменная может принадлежать объекту любого типа. Иными, более точными словами, переменные в языке Smalltalk динамически типизированы. Более точно потому, что сам Smalltalk строго типизирован; все в нем является полноценным объектом, экземпляром класса. В нем нет “примитивным” типам.

Названия переменных и условия

Названия переменных состоят из букв и чисел и могут иметь подчеркивания. Название переменной может начинаться с буквы или подчеркивания. Названия объектов в Smalltalk’е по сравнению с другими языками имеют тенденцию быть длинными, что делает код более легко читаемым. В целях более точного описания название может состоять из двух или более слов. Правило требует, чтобы первая буква каждого введенного слова была заглавной. Это правило не навязывается языком или средствами развития системы, но оно повышает читаемость, то есть облегчает чтение. Следующая таблица показывает условия, в которых применяются заглавные первые буквы в названиях переменных. В общем, начальные буквы показывают область действия переменных: заглавные буквы для общих переменных, строчные – для частных переменных.

             Условия записи заглавными буквами

Тип переменной            Начальная заглавная         Пример

Переменная аргумента                    No                             aString

Переменная экземпляра класса      No                        wordCollection

Название класса                              Yes                              Date

Переменная класса                         Yes                             Location

Переменная экземпляра                  No                                year

Пространство названий                   Yes                          Smalltalk

Общая  переменная                         Yes                      MaximumUsers

Временная переменная                    No                             aDate

В соответствии со стандартом ANSI VisualWorks не допускает использования точек в названиях. В среде VisualWorks, однако, употребляется расширение обозначений при ссылках на соединения. В основном, это относится к общим переменным, классам и названиям из пространства имен, где используется точка. Этот способ обозначения употребляется, чтобы выделить связи в  терминах в пространстве имен и/или в классе и/или общей в переменной, для него определенной. Более подробно об этом говорится ниже.

Частные переменные

Переменные создают связь между названием и изменяемым значением. Название переменной используется, ее значение с областью задания ее пространства имен. Smalltalk в среде VisualWorks имеет несколько видов переменных для разных пространств имен. Следующие переменные являются “частными” в том смысле, что они применимы только для специфических объектов. Общие переменные будут рассмотрены далее.

Временные переменные  

Временная переменная наиболее часто встречается в методе, где предусмотрены временные резервы памяти для аргумента или вычисляемого значения. Его время существования начинается тогда, когда выполнено объявление или блоковое выражение внутри метода, и оканчивается, когда блок или метод оканчивают свою работу и возвращают управление запрашивающему объекту.  Область задания пространства имен этих переменных представляет метод или блок, где они объявлены, и они недостижимы вне этой области. Временная переменная объявляется путем заключения их имен между вертикальными черточками. Объявление  должно следовать за определением сообщения, и обычно за ним следует объяснение метода, так как в противном случае оказывается первой частью определения метода. Например, метод occurrencesOf: для Dictionary (словаря) is:

occurrencesOf: anObject

"Answer how many of the receiver's elements are equal to anObject."

| count |

count := 0.

self do: [:each | anObject = each ifTrue: [count := count + 1]].

^count

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

Множество временных переменных может быть объявлено в том же выражении об объявлении путем заключения их между двумя вертикальными черточками с одним или более знаками пробела (space, tab и т.д.), разделяющими названия каждой переменной. Например,

| var1 var2 var3 |

Объявляет три временных переменных.

Переменные аргумента

Переменные аргумента представляют особый вид временных переменных, объявляемый при определении бинарных методов или ключевых слов. Переменные принимают свои значения от аргументов, поступающих с пришедшими сообщениями. 

Например, класс Time имеет методы экземпляра с названиями hours:minutes:seconds:, определяемые как:

hours: hourInteger minutes: minInteger seconds: secInteger

"Initialize all the instance variables."

hours := hourInteger.

minutes := minInteger.

seconds := secInteger

Этот метод объявляет три временных переменных в их описании, инициализированной в первой строке, и называет их hourInteger, minInteger и secInteger.

Когда объект-клиент посылает это сообщение экземпляру Time, который может иметь название aTime, предусмотрены соответствующие целые. Например,

aTime hours: 11 minutes: 42 seconds: 15

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

По условию временный аргумент получает название для того, чтобы показать тип объекта, к которому он относится (то есть aSet, aString, anInteger). Однако никакая типизация не проводится в обязательном порядке, и любой объект может храниться в любой переменной. Ошибки могут возникнуть в процессе выполнения, если метод не может обратиться к сообщенному объекту.

Переменные экземпляра

Переменные экземпляра содержат данные, специфические для индивидуального экземпляра класса. Значение переменной описывает состояние свойства экземпляра. Переменная экземпляра создается, когда экземпляр производится, и существует, пока существует экземпляр. Область существования названия – это сам экземпляр, который, как объект, может ссылаться на саму переменную. 

Имеются два вида переменных экземпляра, именованные и индексированные. Тип переменной экземпляра определяется для класса при его определении (для более подробной информации отсылаем к главе 4, “Классы и экземпляры”). Чаще используются именованные переменные экземпляра. Переменные объявляются путем названия их при определении  класса в строке-аргументе в ключевом слове instanceVariableNames:. В соответствии с этим каждый экземпляр класса будет иметь перменную экземпляра с этим именем. Например класс Customer может определять переменную экземпляра firstName следующим образом:

ABCorp.Billing defineClass: #Customer

superclass: #{Core.Object}

indexedType: #none

private: false

instanceVariableNames: ' firstName '

classInstanceVariableNames: ''

imports: ''

category: 'Customer-Records'

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

firstName := ‘Bruce’

и другой метод выследит это значение, просто обратившись по имени:

^firstName

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

• #object, for arbitrary objects

• #byte, restricting values to byte values

• #weak, making the class a weak container class, like WeakArray

• #immediate, restricting values to immediate objects such as instances of Character, SmallInteger, and Symbol

• #ephemeron, restricting values to instances of Ephemeron

В классе не применяются индексированные переменные экземпляра, тип индекса указывается как #none. Подробности указаны в разделе “Типы классов” в главе 4 “Классы и экземпляры”. Отдельные экземпляры класса могут иметь разные номера среди индексированных переменных экземпляра. Собрания, например, имеют разные размеры, и потому используется один экземпляр индексированной переменной для каждого элемента. Индексированные переменные экземпляра устанавливают связь между положением индекса и значением, и таким образом к ним осуществляется доступ с помощью сообщений at: и at:put:. Например, если названия принадлежат экземплярам класса Array, то первому элементу массива посылается сообщение 

names at: 1

Чтобы добавить название для четвертого элемента, посылается сообщение

names at: 4 put: ‘Bruce’

в котором сохраняется строка ‘Bruce’ как значение четвертой индексированной переменной экземпляра. 

Класс может определить свои экземпляры, чтобы иметь и обозначенные, и индексированные переменные экземпляра. Например, класс Set определяет свои экземпляры как имеющие и индексированные переменные экземпляра, которые сохраняют значения объекта, так и отдельные именованные переменные экземпляра, как показано при определении класса:

Smalltalk.Core defineClass: #Set

superclass: #{Core.Collection}

indexedType: #objects

private: false

instanceVariableNames: 'tally '

classInstanceVariableNames: ''

imports: ''

category: 'Collections-Unordered'

Подсчет (tally) переменных используется, чтобы записать количество элементов во множества, индексированные переменные используются для хранения отдельных элементов.

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

Переменные экземпляра класса

Переменные экземпляра класса сохраняют данные, которые изменяются с каждым подклассом в иерархии. Они объявляются как часть определения класса и доступ к ним производится только через метод класса.  Например, допустим, что у нас имеется абстрактный класс LanguageDictionary, в котором есть методы просмотра слов с целью проверки произношения и т. п.  Мы задаем в LanguageDictionary переменную экземпляра, называемую wordCollection. Затем создаем серию подклассов, связанных с русским языком, английским языком и так далее.  Класс EnglishLanguage может инициализировать wordCollection, где содержатся английские слова. Другие подклассы могут инициализировать эту переменную по-другому. Но теперь, когда экземпляр любого подкласса запрашивает wordCollection, он получает особую для каждого языка версию.

LanguageDictionary class

       wordCollection ()

 
 

 

 

СинтаксисСинтаксис

 

Переменная экземпляра класса

Преимущества такого подхода состоят в том, что мы просто инициализируем переменную wordCollection один раз в каждом подклассе (в отличие от переменных экземпляра), и все подклассы могут заново применять методы, использующие общее название переменной (в отличие от переменных класса).

Общие переменные

Общие переменные – это переменные, которые могут быть использованы или на которые могут ссылаться многие объекты. В первых реализациях VisualWorks, общие переменные включают переменные класса, переменные пула и глобальные переменные. Эти разные типы переменных объединены в единый тип, названный “общие переменные” (“shared variable”).

Значения общих переменных логически не связаны с любым из одиночных экземпляров объектов. В отличие от переменных экземпляра, у которых каждый объект хранит свое индивидуальное состояние, и переменные экземпляра класса, где каждый класс хранит свое состояние, общие переменные могут быть поделены между множественными объектами. Общие переменные представлены как связи (bindings), которые являются экземплярами либо класса VariableBinding, либо его подкласса InitializedVariableBinding. Соответственно, мы иногда ссылаемся на “связывание” и имеем в виду именно экземпляры одного из этих классов, а не более общий случай присвоения значения.

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

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

Для определения общих переменных используем либо шаблон, описанный в следующих разделах, либо диалог New Shared Variable dialog, Class → New → Shared Variable....

 

Переменные класса

Общие переменные, когда определяются по отношению к классу, заменяют переменные класса, вводившиеся в реализациях, которые предшествовали варианту  5i.

Переменные класса наследованы и доступны самому классу, его экземплярам, его подклассам и их экземплярам. Это справедливо даже, если классы расположены в разных пространствах названий; прямое импортирование не является необходимым. 

Например, класс Date имеет общую переменную, называемую MonthNames, которая хранит массив, содержащий названия 12 месяцев. Было бы пустой тратой сил хранить массив в каждом экземпляре, который является его копией, так как названия остаются одними же и теми для всех экземпляров. После этого он доступен и для экземпляров класса Date и его подклассов, а также экземпляров любого другого класса, который вводит его.

Чтобы определить переменные класса надо:

1 В любом браузере системы выбрать класс, который будет служить пространством имен для переменной, и выбрать таблицу Shared Variables.

2 Выбрать или добавить и выбрать категорию для новой общей переменной в списке методы/общие переменные. Образец для определения отображается на панели с кодом: 

Smalltalk.MyNameSpace.MyClass defineShared: #NameOfBinding

private: false

constant: false

category: 'category description'

initializer: 'Array new: 5'

3 В образце:

• Заменить #NameOfBinding символом, определяющим общие названия переменных, такие как #MySharedObject.

• Установить как частные (private:) поле true, чтобы переменную частной, иначе оставить ее false.  (Обратится ниже к разделу “Частные и открытые общие переменные”).

• Установить как поле constant: на true, если значение переменной не должно изменяться, в противном случае оставить его как false. (Обратиться ниже к разделу “Постоянное и переменное связывание”).

• Ввести в поле initializer: инициализирующее, подобное String, или ввести nil. (Обратиться ниже к разделу “Инициализация общих переменных”).

4 Выбрать Accept в <Operate> меню браузера, чтобы сохранить определение и создать общую переменную. Новая переменная добавлена в список. Ее можно увидеть в любом браузере классов, если выбрать таблицу Shared Variables и ее категорию.

Переменные пула

Общие переменные могут также быть определены прямо в пространстве названий (пространство названий неклассов).  Например, в пространстве названий Graphics определено множество классов и два других пространства названий: SymbolicPaintConstants и TextConstants. Эти пространства названий существуют исключительно как области функционирования названий для собраний общих переменных.

Каждая общая переменная определена непосредственно в пространстве названий. Инициализация значений переменных предусматривается либо по строке определения initializer:, как это и сделано для большинства переменных TextConstant, либо в соответствующем методе инициализации класса, как сделано для переменных SymbolicPaintConstants.

Для этих переменных, чтобы получить к ним доступ в другом пространстве названий, отличном от определенного для них пространства наименований, переменная должна быть импортирована, обычно посредством общего импорта их пространства названий. (Обратиться ниже, к разделу “Импортирующие связывания”). 

Можно определить пул путем создания пространства названий, которое и является пулом, а затем добавить в него общие переменные, используя серию сообщений at:put:. Это было общепринятым подходом к определению словарей пула в версии, предшествующей 5i, и аккуратно перенесено в VisualWorks 7. Для примера просмотрите относящийся к классу SymbolicPaint метод initializeConstantPool.

Более подходит для среды VisualWorks 7 метод, который состоит в определении пространства названий, а затем добавляет к нему общие переменные:

1 В списке браузера системы класс/пространство названий выбирается пространство названий, которое будет содержать пул. Выбирается наибольшее локальное пространство названий, которое дает ощущение широты применения для этих общих переменных. 

2 Выбирается Add→!Name space из меню Class браузера. Определения образца определения пространства названий отображается на панели кода.

 3 Завершается работа над образцом назначением названия пула как и название пространства названий. (Обратиться для завершения этого обсуждения образца к разделу “Создание пространств названий”).

4 Выбирается пространство названий пула, затем из меню класса Class браузера выбирается  Add→Shared Variable. Определение образца общих переменных отображается на панели кода:

Smalltalk defineSharedVariable: #NameOfBinding

private: false

constant: false

category: 'As yet unclassified'

initializer: 'Array new: 5'

5 На образце:

• Заменяется #NameOfBinding символом, определяющим название общей переменной (переменной пула), таким как #MySharedObject.

• Устанавливается для true поле private:, чтобы сделать переменную частной, иначе оставляем для нее false. (Обратиться ниже к разделу “Открытые и частные общие переменные”).

• Устанавливается для true поле constant:, если значение переменной не должно изменяться. В противном случае оставляем для него false. (Обратиться ниже к разделу “Постоянные и изменяющиеся связывания”).

• Обеспечиваем соответствующую категорию: string.

• Вводим инициализирующее выражение, например, String, в поле initializer:, или вводим nil. (Обратиться ниже к разделу “Инициализация общих переменных”).

6 Чтобы сохранить определение и создать общую переменную в браузере выбрается Edit → Accept. С этого момента переменные пула определены и инициализированы.  At this point the pool variables are all defined and initialized. Вы можете давать им определения, делая их частными, постоянными или изменяющимися. Чтобы увидеть эти новые общие переменные, откроем браузер системы, выберем закладку Shared Variables, выберем для пула в списке пространства названий пространство наследованных названий, выберем пространство названий в списке класс/пространство названий и выберем категорию.

 

 

О глобальных переменных

Глобальные переменные редко используются в VisualWorks, так как по большей части уже заменены переменными пула. Даже до версии VisualWorks 5i, только немногие “глобальные элементы системы”, такие как Transcript и Processor остались в системе. В целом они дают немного практики для объектно-ориентированного программирования, так как нарушают инкапсуляцию и поэтому их избегают. 

Взамен глобальных элементов оставшиеся объекты системы определены как общие переменные в пространстве названий, что почти обязательно принимается во всех пространствах названий. Например, класс Transcript в Smalltalk’е определен как общая переменная в пространстве Smalltalk.Core name space.

Чтобы просмотреть эти определения, рассмотрим в браузере системы Smalltalk пространство названий, выберем Core (его основную часть) в списке класс/пространство названий, а затем просмотрим общие переменные. При этом можно искать Transcript, пользуясь встроенным в браузер механизмом поиска (правый верхний угол инструментария). 

В результате общие переменные не будут чисто “глобальными” для системы, так как легко определить пространство названий, которое не импортирует Core (основы).

Для определения общих переменных проделаем:

1 В браузере системы выбираем пространство названий по списку класс/пространство названий, которое является пространством суперназваний. Выбираем наибольшее локальное пространство названий, которое дает уверенность в ее возможной достижимости для общих переменных. Для  максимально широкой возможности выбираем пространство названий Smalltalk’а.

2 Из меню Class браузера выбираем Add → Shared Variable.  Образец определения общей переменной отображается в панели кода:

 

Smalltalk defineSharedVariable: #NameOfBinding

private: false

constant: false

category: 'As yet unclassified'

initializer: 'Array new: 5'

3 In the template:

• Заменяем #NameOfBinding символом, отмечающим название общей переменной, например, такой, как #MySharedObject.

• Чтобы сделать переменную частной, устанавливаем в поле private: true; в противном случае оставляем в нем false. (Ниже обратимся для более подробного рассмотрения к разделу “Открытые и частные общие переменные).

• Если значение переменной не должно изменяться, то устанавливаем true в поле constant:. В противном случае оставляем в нем false. (Обратимся ниже за подробностями к разделу “Постоянные и переменные связывания”).

• Обеспечиваем соответствующую категорию: string.

• Вводим выражение инициализации типа String в поле initializer: или вводим nil. (Обращаемся за деталями ниже к разделу “Инициализация общих переменных”).

4 Чтобы сохранить определение и создать общую переменную выбираем в браузере Edit → Accept. Чтобы увидеть новую общую переменную, откроем браузер системы (System Browser), выберем закладку Shared Variables, в списке пространства названий выберем пространство супер-названий переменных, в списке класс/пространство названий выберем его пространство названий и выберем его категорию

Названия класса и пространств названий

В версиях до 5i названия классов названия классов  хранились как глобальные переменные. В версии 5i оба вида названий и классов, и пространств названий относятся к общим переменным, чьими значениями соответственно служат классы и пространства названий. Так как они играют особую роль в системе, то будут рассмотрены отдельно в следующих главах.  

Постоянное и переменное связывание

Иногда желательно поместить значение общей переменной и обеспечить ее неизменность, то есть постоянство.  Поле constant: в определении общей переменной обеспечивает эту опцию. Если помещенное значение ложно, переменная может быть установлена и инициализирована обычными способами и для любого объекта в системе. (За подробностями обратимся к разделу “Инициализация общих переменных”). Если помещенное значение истинно, то оно не может быть изменено обычными средствами.

Для постоянных общих переменных (хотя это звучит и странно, но они все равно называются переменными) изменение значения требует нового запуска инициализирующей программы и таким образом переменная защищена от изменений значений при запуске. Значение во всех смыслах и при всех целях остается постоянным. Даже метод инициализации класса, который устанавливает переменную, не сможет одолеть этого препятствия.

Заметим, что Вы можете изменить определение общих переменных и, таким образом, превратить ее из переменной в постоянную. Если Вы так делаете, то будьте уверены, что методы, устанавливающие переменную, отныне не работают. 

Общественные и частные общие переменные

Smalltalk’у долго не хватало возможной системы различия между общепринятыми и частными  классами и методами. Переменные были либо частными (экземпляра, класса, класса экземпляра переменные), либо общими (глобальные переменные или переменные пула), в зависимости от вида переменной. Пространства названий и общие переменные обеспечивают способ восполнить эту нехватку, давая возможность управлять импортом на двух уровнях – определением или вводом.

В обоих случаях его создание или введение общая переменная может быть объявлена либо общедоступной, либо частной.

•   Если применено слово частная, она применима для введения пространством названии или класса.

•   Если применено слово связанная, то она не применяется не применяется для ввода СС помощью пространства имен или классов. If a binding is private,

Больше информации об импорте (вводе) получите ниже, в разделе “Импортированное связывание”

Определение связывания как частного или общедоступного

На одном уровне в этом классе каждый отдельный класс, пространство названий и общая переменная объявлены либо как общедоступные, либо как частные введением булева аргумента в поле private:. Когда устанавливается false, то связывание общедоступное и потому может быть импортировано. Когда установлено true, то связывание частное и потому не может импортироваться. На этом уровне термины частный или  общедоступный – это установка представляют собой установку самого объекта и потому безусловны.

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

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

Определение пространства названий, класса или общей переменной, как частной, является исключением, но такая опция  имеется.

Инициализация общих переменных

Имеется много способов инициализации общих переменных. Если Вы определяете инициализирующую строку в определении общей переменной либо как:

• выбираем переменную в браузере, а затем выбираем Initialize shared в меню <Operate> (или меню браузера Metod) или как

• посылаем метод initialize в адрес связывающей ссылки переменной, например:

#{Smalltalk.MyNameSpace.MyBinding} initialize

Эти методы инициализации работают независимо от того, объявлена переменная как константа или нет (объявлено поле constant: или нет).

В случае переменных класса и пула инициализация общих переменных нередко бывает частью инициализации класса. В этом случае значение является частью метода инициализации класса или метода названного initialize.

Например, выбор Initialize shared класса Dummy (модель, макет) может просто установить значение общей переменной (DummyShared), определенное в классе следующим образом:

initialize

"Dummy initialize"

DummyShared := String fromString: ' a b c d e'.

Заметим, что при инициализации общей переменной в методе переменная не должна быть установлена как константа; в поле constant: должно быть установлено false.

Определение значения переменной

Значение по умолчанию для любой переменной  – это объект nil. Чтобы присвоить новое значение переменной, используем оператор присвоения := (двоеточие с последующим знаком равенства), как это сделано в выражении:

prompt := 'Enter your name'

Выражение справа присвоения может быть любым допустимым выражением Smalltalk’а. Следующие примеры все представляют собой действующие выражения присвоения. Они подобны созданию ароматной приправы для мороженного и последующего случайного выбора одной из них:

flavors := #('chocolate' 'vanilla' 'mint chip').

index := (Random new next)* 3.

flavorChoice := flavors at: index truncated + 1

Выбор может быть сделан, когда две или более переменных хранят одно и то же значение, например,

majorLoopCounter := minorLoopCounter := 1

Связанные назначения должны быть использования только литералами или значениями только для чтения. В противном случае обновление одной переменной приносит сторонний эффект подобного изменения значения другой переменной.

Специальные переменные

У трех специальных переменных – self, super и thisContext значение изменяется в соответствии с контекстом, но не может изменяться в соответствии с назначением. 

Наиболее распространенным из этих специальных переменных является self, которая связывается с объектом, выполняемым в текущем сообщении.

В  простейшем случае self позволяет программисту направить новое сообщение отдельному экземпляру, выполняющему текущий метод. На самом деле объект может выполнить другой из его методов. Гипотетический метод doSomething может использовать метод computeX для вычисления числа, например, воспользовавшись выражением self computeX.

Более сложный случай возникает, когда в деле участвует наследование. Допустим, метод doSomething размещен в суперклассе объекта, который получил сообщение doSomething. Но в подклассе введено computeX. Как мы пошлем искателя метода назад, искать computeX иначе, чем просто начать с его суперкласса?

Специальная переменная self является указателем на  объект (в данном случае anObject), который получает сообщение для выполнения (doSomething). Удивительным, но приятным ответом является то, что выражение self computeX все еще работает. Новое сообщение (computeX) направленное к self, относится к объекту, который получает предшествующее сообщение (doSomething).

 

 

Синтаксис

Важно помнить, что self не обязательно обращается к экземпляру класса, чей метод выполняется. В нашем примере self используется в суперклассе, хотя относится к классу. Так, пользуясь методом self, мы автоматически получаем обратное продвижение по иерархии. 

Переменная super очень похожа на self за исключением того, что super искателю метода начать его поиск на одну ступень в иерархии выше исполняемого метода. Это полезно, когда подклассу нужно прибавить операций к суперметоду без дублирования кода в суперметоде. Заметим, что super, по существу, проводит уточнение метода поиска и он не может быть назначен в переменной (как это может быть сделано с self).

Синтаксис

Третья специальная переменная, thisContext, относится к контексту текущего процесса. Тогда, как self  и super широко используются программистами на Smalltalk’е, thisContext редко применяется разработчиками приложений. Его применяют при выполнении системных исключений и при отладке.

Замечание: В части литературы по Smalltalk’у self и super рассматриваются, как псевдопеременные. Однако другие объекты также называются псевдопеременными, что делает термин двусмысленным. Вместо этого мы называем его специальной переменной. 

Необъявленные переменные

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

Чтобы исследовать сущность определения “необъявленная”, выберем в окне запуска Browse → Global и введем undeclared в ускоритель. В результате откроется инспектор пространства имен.

Выражения в сообщениях

Выражения в сообщениях представляют собой важнейшую часть программирования на языке Smalltalk. Они могут иметь три вида: получатель, название метода, и ноль или более аргументов.  В сообщении 9 raisedTo: 2 получателем является 9, названием метода raisedTo:, а аргументом 2. Термин сообщение в техническом смысле относится к селектору метода и аргументам, тогда как выражение в сообщении включает в себя получателя.

Каждое сообщение возвращает объект отправителю сообщения. В только что приведенном примере метод  raisedTo: возвращает экземпляр класса SmallInteger, а именно 81. Есть три способа отметить объект, который будет возвращен методом:

•    По умолчанию, когда получатель метода (self) возвращается отправителю.

•    Оператор возврата (^, вводимый в большинстве клавиатур, как <Shift-6>) перед названием переменной означает, что объект должен быть возвращен. Например выражение ^anObject означает, что anObject должен быть возвращен.

•    Оператор возврата перед выражением сообщения возвращает значение этого выражения. Например, выражение ^3 + 4 означает, что должен быть возвращено число 7.

Точка используется для разделений выражений в сообщении. Отсутствие точки обязательно после заключительного выражения в последовательности.

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

Унарные сообщения

Унарное сообщение имеет получателя и название метода, но не имеет аргументов. Пример унарных сообщений :

1.0 sin.            "Returns the sine of 1.0."

Random new. "Returns a random number generator."

Date today.     "Returns today's date."

 

Бинарные сообщения

Бинарное сообщение использует особый знак, например, знак плюс ($+), в качестве названия метода и имеет один аргумент. Некоторые бинарные селекторы представляют собой комбинацию двух знаков, например, селектор сравнения >= (больше или равно). Символы, допускаемые в бинарных селекторах и правило употребления их описаны в Приложении А “Описание синтаксиса VisualWorks Smalltalk”.

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

 Селекторы бинарных методов

Селектор

Пример

Описание

+

counter + 1

Сложение

-

100 - 50

Вычитание

*

index * 3

Умножение

/

1 / 4

Деление

**

4 ** 3

Возведение в степень

//

13 // -2

Деление нацело (округляет частное до ближайшего следующего целого; в примере -7). Экземпляр точки может быть также округлен этим оператором.

\\

13 \\ -2

Деление по модулю (возвращает остаток после деления; в данном примере -1).

counter < 10

Меньше, чем

<=

index <= 10

Меньше или равен

clients > 5000

Больше, чем

Селекторы

бинарных

методов            (продолжение)

Селектор

Пример

Описание

>=

files >= 2000

Больше или равен

=

counter = 5

Значения равны

~=

length ~= 5

Значения не равны

==

x == y

Один и тот же объект (получатель и аргумент являются одним и тем же объектом или точкой одного и того же объекта)

~~

x ~~ y

Не тот же объект

&

(x>0) & (y>1)

Логическое И (возвращает true, если и получатель, и аргумент истинны, в противном случае false).

|

(x>0) | (y<0)

Логическое ИЛИ (возвращает true, если или получатель, или аргумент ложны).

,

'abc','def'

Соединение двух собраний.

@

200 @ 300

Возвращает экземпляр точки, у которой координата x является получателем, а координата y является аргументом.

->

#Three -> 3

Возвращает экземпляр сообщества, у которого ключ является получателем, а значение аргументом.

<< 

#All << #labels

Создает класс СообщениеПользователя

>> 

#All << #labels >> 'All'

Присваивает идентификатор каталога для класса СообщениеПользователя

 

 

Вторым символом в двухсимвольном не может быть знак минус ( $- ). Другими допускаемыми символами являются: $+, $/, $\, $*, $~, $<, $>, $=, $@, $%, $|, $&, $?, $!, and $,.

Заметим, что выражение присвоения ( := ) не является селектором метода. Кроме того, символ связи (>>), используемый в отладчике и браузерах для ссылка на метод и класс его применения (например, Set>>size, чтобы сослаться на  величину метода экземпляра), не является бинарным селектором.

 

Методы ключевые слова

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

aDate addDays: 5                 "Add five days to aDate."

anArray copyFrom: startIndex to: stopIndex

"Return a copy of that portion of anArray

that begins at startIndex and ends at stopIndex."

Когда имеется более одного ключевого слова, название метода формируется из соединением ключевых слов.  Во втором приведенном примере названием метода является copyFrom:to: (произносится “copyFrom двоеточие to двоеточие”). Ограничений на количество ключевых слов в названии метода нет.

Прагмы

Прагмы представляют собой особый метод синтаксиса, который упрощает объяснение некоторых операций. Они представляют собой псевдокомментарий и определяются следующим синтаксисом:

< pragmaKeyword: ... >

Это можно увидеть при просмотре кода.

Один набор прагм может оказаться полезным при определении пунктов меню. Информация об этом помещена в Руководстве разработчика ГИП.

Программистам на Си понадобится прагма c:, которая обеспечивается сочетанием add-in, связывающим  DLL и Си, как это описывается в Руководстве пользователя соединением Dll и Си.

Общий механизм для определения прагм дается в классе Pragma.

Последовательности сообщений

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

interest := principal * interestRate.

principal := principal + interest.

principal := principal + (principal * interestRate).

Этот метод уменьшает размер кода иногда в ущерб его читаемости. Скобки могут вводиться, как указано в примере, чтобы улучшить читаемость и быть уверенным, что соблюдается порядок выполнения. 

Каскадные сообщения

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

Transcript show: 'This is line one.'.

Transcript cr. "Carriage return."

Transcript show: 'This is line two.'.

Transcript cr.

Transcript show: 'This is line one.'; cr;

show: 'This is line two.'; cr

Порядок анализа сообщений

Когда два сообщения имеют одного анализирующего предшественника, иногда необходимо применить скобки.  Например, выражение 3 + 4 * 5 очень отличается от выражения 3 + (4 * 5), так как бинарные селекторы вычисляются слева направо. Скобки оказываются также необходимыми, когда выражение ключевого слова дается в качестве аргумента для другого выражения ключевого слова. Например, ниже первое выражение справедливо, но во втором предложении селектор метода интерпретирован компилятором как readFrom:on:, чего не может быть.

Time readFrom: (ReadStream on: '10:00:00 pm').

Time readFrom: ReadStream on: '10:00:00 pm'. "WRONG"

Следующие правила подводят итог порядку анализа:

1.    Рассматривать выражения в скобках до выражений без скобок.

2.    Анализировать множественные унарные выражения слева     направо.

3.    Анализировать множественные бинарные выражения слева   направо.

4.    Анализировать унарные сообщение ранее бинарных.

5.    Анализировать бинарные выражения перед ключевыми словами.

Результат следующего фрагмента программы состоит в том, что число напечатано в редакторе системы (System Transcript) — можете ли вы проследить здесь логику, в свете приведенных правил?

| aSet nbr |

nbr := 207.

Transcript show: (aSet := Set new add: nbr + 3 * 5 sin) printString

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

1.   Set new               Устанавливаем новую экземпляр Set.

2.   5 sin                     Вычисляем sin 5 (-0.958924).

3.   nbr + 3                 Прибавляем 3 к nbr (210).

4.   ... * ....                  Умножаем 210 на -0.958924 (-201.374).

5.   .. add: ...              Прибавляем -210.374 в качестве элемента последовательности, созданной на шаге 1.

6.   aSet :=                 Присваиваем последовательность (Set) переменной aSet.

7. ... printString         Преобразуем Set к пригодному для печати ряда (string) виду.

8. Transcript show:   Выдача конечного результата в виде ряда для   представления.

Блоковые выражения

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

Блоковое выражение заключено в квадратные скобки, как ниже:

 [index := index + 1.

anArray at: index put: 0]

Сообщение внутри блока не посылается до тех пор блоковый объект не получит унарное сообщение value. Следующее выражение дает тот же результат:

index := index + 1.

[index := index + 1] value.

В блоке могут находиться до 255 отдельных аргументов. Названия аргументов могут быть перечислены внутри скобок.  Названию каждого аргумента предшествует двоеточие. За последним названием аргумента помещается вертикальная черточка. Например:

[:counter | counter := counter + 1]

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

value: anObject

value: anObject value: anObject

value: anObject value: anObject value: anObject

valueWithArguments: anArray

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

[:counter | counter := counter + 1] value: 3

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

[ :arg1 :arg2 |

| temp1 temp2 |

statement1.

statement2.

...]

Условия форматирования

Компилятор игнорирует заголовки, знаки возврата каретки и дополнительные пробелы. Условия форматирования изменяются, но требования к легкости чтения сводятся к следующему:

1. Определение сообщения начинается слева и все остальное содержимое метода определяется на одном уровне.  

2. Внизу комментария к методу и в качестве разделения частей большого метода оставляется пустая строка. 

3. Следовать за каждой запятой, завершающейся знаком возврата каретки. 

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

Браузер кода в среде VisualWorks языка Smalltalk обеспечивает выполнение команды format для автоматического выполнения этих правил.

 

Наверх страницы

Внимание! Не забудьте ознакомиться с остальными документами данного пользователя!

Соседние файлы в текущем каталоге:

На сайте уже 21970 файлов общим размером 9.9 ГБ.

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

Не нашли нужный документ? Воспользуйтесь поиском по содержимому всех файлов сайта:



Каждый день, проснувшись по утру, заходи на obmendoc.ru

Товарищ, не ленись - делись файлами и новому учись!

Яндекс.Метрика