5.08. Типы данных и переменные
Типы данных и переменные
Поскольку все типы данных здесь являются объектами, давайте их разберём.
- Числа. В 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 умеет работать с рациональными числами точно.
- Строки заключаются в одинарные кавычки:
'Hello, world!'
'Привет, Smalltalk!'
Строки — объекты, поддерживающие множество методов:
'hello' size "→ 5"
'hello' at: 1 "→ $h"
'hello' reversed "→ 'olleh'"
'hello' asUppercase "→ 'HELLO'"
'hello' includes: $e "→ true"
'hello' copyWith: $! "→ 'hello!'"
Строки изменяемы? Нет. Но можно создавать новые:
('hello' , ' world') trimBoth "→ 'hello world'"
Оператор , — это бинарное сообщение, определённое для строк: конкатенация.
- Символы записываются с помощью решётки:
#имя
#name
#x
#doSomething
#hello_world
#'with spaces' "можно в кавычках, если есть спецсимволы"
Чем отличается 'name' от #name?
Строка 'name' | Символ #name |
|---|---|
| Изменяемый объект (в теории) | Неизменяемый |
| Может быть много копий | В системе — только один экземпляр |
| Используется для текста | Используется как идентификатор, ключ, имя метода |
Символы — как атомарные метки. Их часто используют как ключи в словарях, для отправки динамических сообщений, и в рефлексии.
- Логические значения: true, false, nil. Собственно, мы их уже разобрали.
(x > 0) ifTrue: [ 'positive' ] ifFalse: [ 'negative' ]
nil isNil "→ true"
true not "→ false"
false or: [ true ] "→ true"
- Коллекции.
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.
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"
- Блоки кода.
[ 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
:= — это синтаксис, а не сообщение. Нельзя его переопределить.
Переменные бывают нескольких видов:
| Вид (тип) | Область видимости | Пример |
|---|---|---|
| Локальные | В пределах метода или блока | ` |
| Параметры метода | Входные аргументы | doSomething: x |
| Экземплярные | Приватные переменные объекта | Объявляются в классе: instanceVariableNames: 'name age' |
| Классовые | Общие для всех экземпляров класса | classVariableNames: 'Counter' |
| Глобальные | Доступны везде | Transcript, Smalltalk, Date |
| Специальные | Встроенные (self, super, true, false, nil) | self doSomething |
Пример объявления экземплярных переменных:
Object subclass: #Person
instanceVariableNames: 'name age'
classVariableNames: 'NextId'
package: 'MyApp'
Теперь каждый экземпляр Person будет иметь свои name и age.
Все объекты в Smalltalk происходят от Object — базового класса.
Но есть и более глубокие уровни:
- Object — корень почти всей иерархии.
- ProtoObject — родитель Object, имеет минимум методов.
- Behavior — абстрактный класс для всего, что может выполнять код.
- Class — тоже объект, экземпляр Metaclass.