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

Типы данных и переменные в Smalltalk

Разработчику Архитектору

О чём эта статья

Тип определяется объектом в переменной, а не объявлением int. Числа, строки '...', #symbol, массивы — пробуйте в Playground (первая программа).

Дальше: Справочник Smalltalk · Основы языка (сообщения и Операции коллекций)

Play ITЗагрузка интерактивного демо…

Play ITЗагрузка интерактивного демо…


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

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

  1. Числа. В Smalltalk числа — объекты, и с ними можно делать всё, что угодно.
42 "Integer"
3.14 "Float"
1/3 "Fraction — дробь, не потеря точности!"
16rFF "Шестнадцатеричное: 255"
2r1010 "Двоичное: 10"

Они отвечают на сообщения:

42 factorial "→ 1405006117752879898543142606244511569936384000000000"
3.14 squared "→ 9.8596"
(1/3) * 3 "→ 1 (без потери точности!)"

Причем, 1/3 — это объект класса Fraction, а не приближённое значение. Smalltalk умеет работать с рациональными числами точно.

  1. Строки заключаются в одинарные кавычки:
'Hello, world!'
'Привет, Smalltalk!'

Строки — объекты, поддерживающие множество методов:

'hello' size "→ 5"
'hello' at: 1 "→ $h"
'hello' reversed "→ 'olleh'"
'hello' asUppercase "→ 'HELLO'"
'hello' includes: $e "→ true"
'hello' copyWith: $! "→ 'hello!'"

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

('hello' , ' world') trimBoth "→ 'hello world'"

Оператор , — это бинарное сообщение, определённое для строк: конкатенация.

  1. Символы записываются с помощью решётки: #имя
#name
#x
#doSomething
#hello_world
#'with spaces' "можно в кавычках, если есть спецсимволы"

Чем отличается 'name' от #name?

Строка 'name'Символ #name
Текст, последовательность символовАтомарный идентификатор
Много равных по содержимому копийОдин экземпляр на имя в образе
Методы: size, ,, asUppercaseСелекторы методов, ключи Dictionary

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

  1. Логические значенияtrue, false, nil. Собственно, мы их уже разобрали. Проверка "значение есть" перед доступом к полям — Проверка и валидация и Обработка null.
(x > 0) ifTrue: [ 'positive' ] ifFalse: [ 'negative' ]
nil isNil "→ true"
true not "→ false"
false or: [ true ] "→ true"
  1. Коллекции.

Ниже — синтаксис Pharo; интерактивные схемы коллекций показаны на псевдокоде (JavaScript) для сравнения с другими языками раздела.

Play ITЗагрузка интерактивного демо…

Array — массив фиксированного размера:

#(1 2 3 4) "литерал массива"
Array with: 1 with: 2 with: 3 "создание"

OrderedCollection — динамический список:

| list |
list := OrderedCollection new.
list add: 1; add: 2; add: 3.
list removeLast.

Play ITЗагрузка интерактивного демо…

Dictionary — ассоциативный массив (ключ → значение):

| dict |
dict := Dictionary new.
dict at: #name put: 'Alice'.
dict at: #age put: 30.
dict at: #name "→ 'Alice'"

Можно использовать символы как ключи.

Set — множество (уникальные элементы):

| set |
set := Set new.
set add: 1; add: 2; add: 1. "вторая единица не добавится"
set size "→ 2"
  1. Блоки кода.
[ 2 + 3 ] "блок без параметров"
[ :x | x * x ] "с одним параметром"
[ :a :b | a + b ] "с двумя"

Блоки кода могут храниться в переменных, передаваться как аргументы. выполняться через value, value:, value:value: и т.д.

В Smalltalk переменные не имеют типа. Они просто ссылаются на объекты. Переменные объявляются внутри метода, блока или скрипта с помощью вертикальных черт:

| name age total |

Это — локальные переменные.

Пример:

| name greeting |
name := 'Alice'.
greeting := 'Hello, ', name.
Transcript show: greeting.

Никаких var, let, const, int, String. Только | имена |.

Оператор присваивания — := (двоеточие + равно).

count := 0
name := 'Bob'
items := OrderedCollection new
isReady := true

:= — это синтаксис, а не сообщение. Нельзя его переопределить.

Переменные бывают нескольких видов:

ВидОбласть видимостиПример
ЛокальныеМетод или блокобъявление count в `
ПараметрыАргументы методаsetName: aString
ЭкземплярныеСостояние объектаinstanceVariableNames: 'name age'
КлассовыеОбщие для классаclassVariableNames: 'Counter'
ГлобальныеВесь образTranscript, Smalltalk
ПсевдопеременныеКонтекст выполненияself, super, true, false, nil

Пример объявления экземплярных переменных:

Object subclass: #Person
instanceVariableNames: 'name age'
classVariableNames: 'NextId'
package: 'MyApp'

Теперь каждый экземпляр Person будет иметь свои name и age.

Все объекты в Smalltalk происходят от Object — базового класса.

Но есть и более глубокие уровни:

  • Object — корень почти всей иерархии.
  • ProtoObject — родитель Object, имеет минимум методов.
  • Behavior — абстрактный класс для всего, что может выполнять код.
  • Class — тоже объект, экземпляр Metaclass.