Классы, объекты и конструкторы
Класс — это чертёж, объект — изделие по нему; так данные и поведение объединяются в одну сущность.
Суть: класс описывает поля (данные) и методы (поведение). Конструктор создаёт объект и заполняет поля. Dart предлагает компактный синтаксис конструкторов, который экономит десятки строк.
У Dart-классов есть приятная мелочь — геттеры и сеттеры, которые выглядят как поля, но за ними стоит вычисление. Например, у класса Rectangle можно объявить double get area => width * height; и обращаться к нему как к свойству: rect.area. Это позволяет прятать логику за простым именем и менять реализацию, не трогая код, который этим свойством пользуется. Геттеры повсюду в исходниках Flutter.
Пока данные лежат в отдельных переменных, легко перепутать, чьё имя и чей возраст. ООП решает это: вы объединяете связанные данные и действия над ними в класс. User хранит имя и возраст и умеет здороваться. Каждый конкретный пользователь — это объект (экземпляр) класса.
class User {
final String name;
final int age;
// конструктор с сокращённым синтаксисом this.
User(this.name, this.age);
// метод — поведение объекта
String greet() => 'Привет, я $name, мне $age';
}
void main() {
final u = User('Аня', 20); // создаём объект
print(u.name); // Аня
print(u.greet()); // Привет, я Аня, мне 20
}
Запись User(this.name, this.age) — фирменная краткость Dart. В других языках пришлось бы писать this.name = name; вручную; здесь this. в параметрах сразу присваивает значение полю.
Как работают конструкторы под капотом
Конструктор — это специальный метод, который вызывается при создании объекта и гарантирует, что все обязательные поля заполнены. У класса может быть несколько конструкторов через именованные конструкторы: User.guest(), User.fromJson(...). Это удобно, когда объект можно создать разными способами.
class User {
name, age поля (данные)
greet() метод (поведение)
}
|
| User('Аня', 20) обычный конструктор
| User.guest() именованный конструктор
v
+----------------+ +----------------+
| объект: Аня,20 | | объект: Гость,0| разные экземпляры
+----------------+ +----------------+
class User {
final String name;
final int age;
User(this.name, this.age);
// именованный конструктор
User.guest() : name = 'Гость', age = 0;
// именованный конструктор с именованными параметрами
User.named({required this.name, this.age = 18});
}
final guest = User.guest();
final bob = User.named(name: 'Боря');
Во Flutter каждый виджет — это класс, а его создание — вызов конструктора с именованными параметрами. Поэтому понимание классов и конструкторов напрямую переносится на чтение любого Flutter-кода.
# Аналог класса Dart с обычным и "именованным" конструктором
class User:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def guest(cls): # аналог именованного конструктора
return cls('Гость', 0)
def greet(self):
return f'Привет, я {self.name}, мне {self.age}'
u = User('Аня', 20)
g = User.guest()
print(u.greet())
print(g.greet())
Частые ошибки
- Забыть заполнить
final-поле в конструкторе — компилятор не позволит создать объект. - Писать
this.name = nameвручную, когда есть краткая формаthis.nameв параметрах. - Путать класс и объект. Класс — чертёж, объект — конкретное изделие, созданное конструктором.
Best practices
- Делайте поля
final, если объект не должен меняться, — это безопаснее и дружит с виджетами. - Используйте именованные конструкторы для разных сценариев создания:
fromJson,empty,guest. - Имена классов — в UpperCamelCase:
UserProfile, а неuserprofile.
Когда классов в проекте становится много, на первый план выходит инкапсуляция — сокрытие внутренних деталей. В Dart приватность задаётся подчёркиванием в начале имени: поле _counter или класс _HomeState доступны только внутри своего файла. Именно поэтому объекты состояния виджетов принято называть с подчёркивания — они служебные и не должны быть видны снаружи. Привыкайте скрывать всё, что не является частью публичного контракта класса.
Итог: класс объединяет данные и поведение, а конструктор создаёт объекты. Краткий синтаксис this. и именованные конструкторы — это то, что вы увидите в каждом виджете Flutter, ведь виджеты и есть классы.