Smalltalk в примерах/Специальные переменные, буквы и символы: различия между версиями

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

Версия от 09:59, 5 апреля 2007

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


Пары символов

Есть несколько пар символов которые имеют особое значение когда они используются вместе. Браузер VisualWorks делает простым манипулирование с текстом и парами символов. Ты можэш заключить блок текста в пару символов выделив его и затем нажав \emph{Esc-leftCharacter} (---). Ты можэш выделить весь текст между парой символов дважды щёлкнув между символом и текстом. Ты можэш убрать пару символов выделив тектс между парой и затем нажав \emph{Esc-leftCharacter}.


Это комментарий

Текст между двойными кавычками это текст комментария и он не компилируется. Ты можэш пометить блок текста как комментарий выделив его и затем нажав \emph{Esc-"}.


'Это строка'

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


(2*3)

Заключение выражэния в круглые скобки даёт ему наивысшый приоритерт. Т.е., \verb|1+(2 * 3)| означеет что \verb|2 * 3| вычислится до прибавления результата к \verb|1|. Круглые скобки такжэ используются для заключения литеральных массивов (см. далее).


[некоторый код]

Окружэние кода квадратными скобками создаёт экзэмпляр BlockClosure. Смотри нижэ раздел Автоматически создаваемые объекты.


Приставки

$ Знак доллара это приставка для создания экзэмпляра класса Буква. Смотри нижэ раздел Автоматически создаваемые объекты.


\# \potom


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

Спецыальная переменная \emph{сам} это получатель сообщения, или объект выполняющий метод. Ты используеш \emph{сам} когда объект хочет послать сообщение себе. Это описано более полно в Главе 2, Сообщения.


Спецыальная переменная \emph{супер} ссылается на суперкласс класса в котором \emph{определён} текущий выполняемый метод. Это описано более полно в Главе 2, Сообщения.


\potom


Transcript cr; show: thisContext printString.

Присваивание

= используется для присваивания значения переменной. Например,


число := 3.

Присвоение выполяется последним в предложэнии (исключая возвращаемое значение). Таким образом, следующая строка присваивает строку '68' переменной x.


x := 67.8 округлить минус строкаДляПечати копироватьОт: 2 до: 3.

Оператор присвоения обысно называется 'становится' или 'двоеточие равно' при разговоре. При использовании для присваивания спецыального названия отличного от 'равно' даёт меньшую вероятность того что ты напечатаеш так: \verb|число = 3|, что означает посылку сообщения числу с аргументом 3, и возвращение значения типа Логический.


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


x := y := 3.

Возвращаемое значение

Символ шляпки (\^{}) это символ возвращаемого значения. Если выполняющейся строкой явяется \verb|^3|, выполнение метода закончится и он возвратит МалоеЦэлое со значением 3. \^{} выполняется в самую последнюю очередь в предложэнии. В следующем примере переменная \emph{instVar} получит значение $-3$, затем значение instVar (т.е. $-3$) будет возвращено из метода.


^instVar := 3.14 усечь минус.

По умолчанию метод возвращает \emph{сам}. То есть, если выполнение метода доходит до конца без явного выполнения (\^{}), он возвращает \emph{сам}. \potom. \potom.


Иногда ты можэш увидеть довольно сложно выглядищее возвращаемое значение. В следующих примерах приведены два наиболее часто встречающихся случая использования (\^{}). В первом примере, ты можэш думать о возвращении из блока или \potom. Во втором примере, мы возвращаем результат построения новой совокупности за одну операцыю вместо помещения новой совокупности во временную переменную и затем возвращения этой переменной.


^объектОдин > объектДва
  истина?: [объектОдин]
  лож?: [объектДва]
^некотораяСовокупность
  собрать: [ :каждый | сам manipulate: каждый]

Разделитель предложений

Точка (.) это разделитель предложэний. Если есть два предложэния, первое предложэние нуждается в точке чтобы дать компилятору понять что первое предложэние закончилось и второе начинается. Пропуск точки это одна из самых распространённых ошыбок и обычно она вызывает исключение сообщениеНеПонятно когда Смолток рассматривает первое слово во втором предложэнии как сообщение которое посылается результату выполнения первого предложэния. Лучшым способом проверить нет ли пропущенных точек запустить форматировщик после написания метода. Если метод выглядит не так как ты ожыдаеш, ты возможно пропустил точку.


Заметь что точка это \emph{не} ограничитель предложэний. Метод с одним предложэнием не нуждается в точке. Не нужна точка и для последнего предложэния в методи или блоке. Это отличается от C++ где точка с запятой это ограничитель и она нужна для всех выражэний. Однако точка поставленая после предложэния где она не нужна это не ошыбка. Я обычно не забочусь о лишних точках. После того как я заканчиваю писать метод и метод компилируется (т.е. он успешно принимается), я запускаю форматировщик, который удаляет все ненужные скобки и точки.


Каскадирование

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


Transcript cr; показать: 'это строка'.
аСовокупность
  добавить: 'этот';
  добавить: 'тот'.
печататьНа: аПоток
  аПоток
     печать: сам класс;
     crtab;
     печать: сам перЭкзОдин.

Если ты используеш каскадирование, обычно принятой практикой является помещение сообщений в одну строку, затем каждый каскад помещается на отдельной строке, \potom. Короткие сообщеник такие как cr, или tab обычно помещаются на той жэ строке. К сожалению форматировщик разрушает отступы определённые тобой для каскада. Из за этого, я часто указываю получателя каждый раз и использую точку для разделения предложэний. При этом нет потери производительности.


Автоматически создаваемые объекты

Есть некоторые объекты которые создаются автоматически вместо явного посылания сообщения \verb|новый| классу.


Малые целые

4 --- экзэмпляр класса МалоеЦэлое можэт быть создан просто при использовании цэлого значения. Одной из интересных особенностей цэлых --- ты не можэш получить переполнения цэлого если ты добавиш единицу к самому большому МаломуЦэлому, возвращаемое значение метода + это БольшоеПоложытельноеЦэлое. Попробуй выполнить


МалоеЦэлое максимальноеЗначение + 1.

Числа с плавающей точкой

3.14 --- экзэмпляр класса ПлавающаяТочка можэт быть создан при использовании значения с плавающей точкой.


Строки

\verb|'это строка'| --- экзэмпляр Строки (на самом деле подкласса Строки) можэт быть создан при заключении поселдовательности букв в одинарные кавычки. Строка это забавный класс потому что дажэ если ты напишыш \verb|Строка новый| ты по прежнему получиш экзэмляр подкласса Строки. Для создания строки содержащей одинарную кавычку, используй две одинарные кавычки для определения кавычки в строке. Например,


'You cant do that'

Буквы

\$А --- экзэмпляр Буквы можэт быть создан при помощи предшэствующего знака доллара и буквы. Например, буква Х создаётся при написании \$Х. Ты можэш создать экзэмпляр пробела, табуляцыи, --- и другие неизображаемые символы таким жэ способом; например, ты можэш создать пробел как \$\ и перевод строки набрав \$ и нажав ввод. Однако, такой способ треден для чтения, поэтому предпочтительный способ создания таких букв --- послать соответствующее сообщение Букве (например, \verb|Буква пробел| или \verb|Буква cr|). Чтобы узнать какие буквы могут быть созданы при помощи посылки сообщений, смотри сообщения стороны класса Буквы или выполни \verb|Буква именаКонстант|.


Символы

\#notFound --- экзэмпляр Символа можэт быть создан при помощи приставки \# и последовательности букв. Если тебе нажэн символ содержащий пробелы, ты можэш заключить имя символа в одинарные кавычки. Например, \#'not found'. Если ты inspect этот символ, он будет показываться вместе с кавычками но когда ты посмотриш первый символ, ты увидиш что это \$n вместо одинарной кавычки.


Массивы

\#(1.1 \$а 'hi') --- экзэмпляр Массива можэт быть создан путём помещения других автоматически создаваемых объектов между скобками с предшэствующим символом \#. Заметь пробелы между элементами массива. Заметь так жэ что элементы массива не обязаны быть одного типа.


Ты не можэш использовать эту конструкцыю для объектов нуждающихся в сообщении для создания. Т.е. ты \emph{не} можэш сказать \#(1 (Буква cr)) и ожыдать что ты получиш массив из цэлого числа и буквы. Однако, ты \emph{можэш} создать литеральный массив который содержыт другие литеральные массивы, такой как \#(1 \#(1.1 'hi' \#(2 \#symbol)))


Блоки

['привет' эхо] --- экзэмпляр BlockClosure можэт быть создан путём помещения кода между квадратными скобками. Код не будет выполнен до того как он не получит сообщение из группы \verb|значение|. Ты можэш поместить код в блок и затем передать его другому методу где он будет выполнен. Блоки часто помещаются в Dictionaries для последующего обращения и выполнения. Заметь что значение блока это значение последнего предложэния выполненого в блоке. Т.е. значение \verb|[3. 4. 5. 1]| --- 1.


У блока могут быть параметры, которые определяются при помощи двоеточия перед именем параметра и отделяются вертикальной чертой от оставшэгося кода. Например [ :параметр | параметр эхо ]. В блоках такжэ могут быть временные переменные, которые помещаются между вертикальными чертами. Например, [ :параметр || временно | временно := параметр * 2. временно эхо].


---


---


[ :parameter | parameter echo ] clean
[ :parameter | | temp | temp := parameter ] clean
[ :parameter | self foo: parameter ] copying (note the self)
[ methodTemporary echo ] copying or full
[ :parameter | A parameter * 3 ] full


\= и \=\=

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


Сообщение = возвращает \emph{истину} если два объекта равны, в то время как сообщение == возвращает \emph{истина} если два объекта \emph{идэнтичны}. Что это означает? (Сообщения противоположные = и == --- \~{} и \~{}\~{}.)


Идентичность

Два объекты \emph{идэнтичны} когда они \emph{точно} один и тот жэ объект. Смолток узнаёт что объект идентичны если они имеют один и тот жэ указатель на объект. Указатель на объект это 32 битная величина, некоторые биты несут информацыю о том где находится значение или значение объекта. Если у тебя есть объект сотрудник, указатель на объект будут отражать объект сотрудник который существует где-нибудь в памяти. Два объект сотрудник идэнтичны если указатели на объект ссылаются на одно и то жэ место в памяти.


С другой стороны, некоторые объекты могут быть представлены полностью 32 битами. Такие объекты возвращают \emph{истину} когда им посылается сообщение \verb|прямой?|, и сейчас это объекты классов \emph{МалоеЦэлое} и \emph{Буква}. (Максимальное значение МаловаЦэлова меньшэ чем максимальное значение 32 битного цэлова потому что три бита используется для определния что МалоеЦэлое а не указатель на объект.) Из за способа хранения, одинакова названные экзэмпляры Символа тожэ идэнтичны.


3 == 3             истина
$а == $а           истина
#абв == #абв       истина
истина == истина   истина
nil == nil         истина
'абв' == 'абв'     лож
3.14 == 3.14       лож
#(1 $а) == #(1 $а) лож

Если ты рассмотриш следующий пример, ты найдёш что x идэнтичен y. Это происходит из за того что присваивание не копирует значение; оно связывает объект с новой переменной т.е. обе переменные содержат один и тот жэ объект.


x := #(1 $a).
y := x.
x == y             истина

\subsection{Равенство}

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


'абв' == 'абв'     лож
3.14 == 3.14       лож
#(1 $а) == #(1 $а) лож

Если ты определиш новый класс, как метод сравнения по умолчанию работает когда два объекта сравниваются? Ответ ---. Если ты посмотриш как определён метод сравнения по умолчанию в классе Объект ты увидеш что он использует сравнение на идэнтичность. Т.е. = просто работает как \verb|^сам == аОбъект|.


Если ты определиш свой собственный метод сравнения ты должэн написать метод \verb|hash| и наоборот. Два одинаковых объект должны иметь одинаоквоэ хэш значение. Причина по которой \verb|hash| и = ходят рука об руку --- некоторые совокупности помещают объекты используя хэшырование (такие как Словарь, Множэство и Мешок).


---.


MyClass>>=
  anObject class == self class ifFalse: [ ^ false ].
MyClass>>=
  (anObject isKindOf: self class) ifFalse: [ ^ false ].