Классы и конструкторы
Класс в Scala объявляется так коротко, что параметры конструктора умещаются прямо в его имени.
«Меньше шаблонного кода — больше видно сути: класс описывает, что объект знает и умеет.»
Класс — это шаблон для создания объектов. В Scala параметры основного конструктора пишутся сразу после имени класса. Это убирает горы повторяющегося кода, привычного по Java.
class Point(val x: Int, val y: Int):
def distanceTo(other: Point): Double =
val dx = x - other.x
val dy = y - other.y
math.sqrt(dx * dx + dy * dy)
val p1 = Point(0, 0)
val p2 = Point(3, 4)
println(p1.distanceTo(p2)) // 5.0Обратите внимание: val x в скобках сразу создаёт неизменяемое поле, доступное снаружи. Если написать var, поле будет изменяемым. Без ключевого слова параметр виден только внутри конструктора.
Создание объектов без new
В Scala 3 можно создавать объекты без слова new — Point(3, 4) вместо new Point(3, 4). Это делает код чище.
Тело класса и инициализация
Любой код в теле класса (вне методов) выполняется при создании объекта — это часть конструктора.
class Account(val owner: String, initial: Int):
var balance = initial // изменяемое поле
println(s"Создан счёт для $owner") // выполнится при new
def deposit(amount: Int): Unit =
balance += amount
val acc = Account("Иван", 100) // печатает сообщение
acc.deposit(50)
println(acc.balance) // 150Та же идея на Python ▶
# Класс на Python — конструктор __init__
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance_to(self, other):
dx = self.x - other.x
dy = self.y - other.y
return math.sqrt(dx * dx + dy * dy)
p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance_to(p2)) # 5.0class Point ( val x: Int , val y: Int )
^ \__________________/
имя параметры конструктора = поляКак работает под капотом (JVM)
Scala-класс компилируется в обычный класс JVM. Параметры конструктора с val становятся приватными полями с автоматически сгенерированными методами-геттерами. Код в теле класса перемещается в конструктор JVM (<init>). Когда вы пишете Point(3, 4) без new, компилятор всё равно генерирует вызов конструктора JVM — это просто синтаксический сахар. Поэтому Java-код может использовать ваши Scala-классы как родные.
Частые ошибки
- Забыть
val/varу параметра. Тогда он не станет полем и будет недоступен в методах после конструктора. - Лепить
varпо умолчанию. Предпочитайтеval-поля для неизменяемых объектов. - Тяжёлая логика в теле класса. Помните: она выполняется при каждом создании объекта.
Best practices
- Делайте поля
val, если объект не должен меняться. - Создавайте объекты без
new— это идиоматично для Scala 3. - Для чистых данных без поведения предпочитайте
case class(изучим в разделе про паттерн-матчинг).
Класс в Scala против класса в Java
Если вы знакомы с Java, лаконичность Scala-классов поначалу удивляет. То, что в Java занимает десятки строк — приватные поля, конструктор, геттеры — в Scala умещается в одну строку с параметрами конструктора. Это не косметика: меньше шаблонного кода означает меньше места для ошибок и больше внимания к сути. Вы сразу видите, какие данные несёт объект, не продираясь сквозь церемонии.
При этом важно выбирать правильный инструмент. Обычный class подходит, когда у объекта есть поведение, состояние или идентичность. Но для чистых структур данных — точек, заказов, конфигураций — почти всегда лучше case class, который мы изучим позже: он бесплатно даёт сравнение по значению, удобный вывод и поддержку паттерн-матчинга. Привыкайте спрашивать себя: это объект с поведением или просто пакет данных?
Полезно с самого начала держать в голове разделение ответственности: класс описывает одну сущность и её поведение, не пытаясь делать всё сразу. Если класс разрастается и начинает отвечать за слишком многое, это сигнал разбить его на части или вынести данные в отдельную структуру. Маленькие, сфокусированные классы проще тестировать, переиспользовать и понимать спустя месяцы после написания.
Итоги. Класс объявляется с параметрами конструктора в скобках; val/var делают их полями. Объекты создаются без new. Дальше — объекты-одиночки и companion-объекты.