Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Immutable объекты в Dart
Immutable (неизменяемые) объекты — это объекты, состояние которых не может быть изменено после создания. В Dart это критически важно для производительности и управления состоянием в Flutter.
Что такое Immutable?
Неизменяемый объект
// Immutable класс
class User {
final String name;
final int age;
final String email;
User({
required this.name,
required this.age,
required this.email,
});
// Нельзя менять свойства!
// user.name = "John"; // Ошибка!
}
// Использование
final user = User(name: "Alice", age: 30, email: "alice@example.com");
// user неизменяем
Аннотация @immutable
Указывает, что класс должен быть immutable:
import 'package:flutter/foundation.dart';
@immutable
class Point {
final double x;
final double y;
const Point({required this.x, required this.y});
// Если забыть final — ошибка анализатора!
}
Const конструкторы
Для максимальной оптимизации используются const конструкторы:
class Color {
final int red;
final int green;
final int blue;
// Const конструктор — все параметры final
const Color({
required this.red,
required this.green,
required this.blue,
});
}
// Const объекты создаются один раз и переиспользуются
const color1 = Color(red: 255, green: 0, blue: 0);
const color2 = Color(red: 255, green: 0, blue: 0);
print(identical(color1, color2)); // true! Один и тот же объект
Immutable модели данных
Простой пример
@immutable
class Product {
final String id;
final String name;
final double price;
final bool inStock;
const Product({
required this.id,
required this.name,
required this.price,
required this.inStock,
});
// Методы для создания модифицированной копии
Product copyWith({
String? id,
String? name,
double? price,
bool? inStock,
}) {
return Product(
id: id ?? this.id,
name: name ?? this.name,
price: price ?? this.price,
inStock: inStock ?? this.inStock,
);
}
}
copyWith() для изменений
Вместо изменения объекта создаем новый:
final product = Product(
id: "1",
name: "Laptop",
price: 999.99,
inStock: true,
);
// Не меняем — создаем новый объект!
final updated = product.copyWith(
price: 899.99,
inStock: false,
);
print(product.price); // 999.99 (не изменился)
print(updated.price); // 899.99 (новый объект)
Immutable в Flutter State Management
Без Immutable (плохо)
class UserState {
User? user;
bool isLoading = false;
String? error;
// Мутируем состояние — флаттер может не заметить изменений!
void setLoading(bool loading) {
isLoading = loading; // Плохо!
}
}
С Immutable (хорошо)
@immutable
class UserState {
final User? user;
final bool isLoading;
final String? error;
const UserState({
this.user,
this.isLoading = false,
this.error,
});
// Создаем новое состояние
UserState copyWith({
User? user,
bool? isLoading,
String? error,
}) {
return UserState(
user: user ?? this.user,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}
// Использование
final state = UserState(isLoading: true);
final newState = state.copyWith(isLoading: false, user: userData);
Immutable в BLoC и Provider
Provider с Immutable моделью
@immutable
class AppState {
final List<Todo> todos;
final String? selectedId;
const AppState({
required this.todos,
this.selectedId,
});
}
class AppNotifier extends StateNotifier<AppState> {
AppNotifier() : super(AppState(todos: []));
void addTodo(Todo todo) {
// Создаем новое состояние
state = AppState(
todos: [...state.todos, todo],
selectedId: state.selectedId,
);
}
void toggleTodo(String id) {
state = state.copyWith(
todos: state.todos.map((t) {
return t.id == id ? t.copyWith(done: !t.done) : t;
}).toList(),
);
}
}
Comparison и Equality
Для immutable объектов важно сравнение:
@immutable
class User {
final String id;
final String name;
const User({required this.id, required this.name});
// Переопределяем equals и hashCode
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is User &&
runtimeType == other.runtimeType &&
id == other.id &&
name == other.name;
@override
int get hashCode => id.hashCode ^ name.hashCode;
}
// Теперь можно сравнивать
final user1 = User(id: "1", name: "Alice");
final user2 = User(id: "1", name: "Alice");
print(user1 == user2); // true! Даже разные объекты
Freezed пакет для автогенерации
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
required String email,
}) = _User;
}
// Автоматически генерируются:
// - copyWith()
// - operator ==() и hashCode
// - toString()
final user = User(id: "1", name: "Alice", email: "alice@example.com");
final updated = user.copyWith(name: "Bob"); // Автогенерированный метод
Практический пример в Widget
class TaskWidget extends StatelessWidget {
final Task task; // Immutable!
const TaskWidget({required this.task});
@override
Widget build(BuildContext context) {
// Flutter может оптимизировать, т.к. task не изменяется
return Card(
child: ListTile(
title: Text(task.title),
subtitle: Text(task.description),
trailing: Checkbox(
value: task.isDone,
onChanged: (value) {
// Создаем новый task, не мутируем старый
final updated = task.copyWith(isDone: value);
context.read<TaskProvider>().updateTask(updated);
},
),
),
);
}
}
Преимущества Immutable объектов
- Производительность — Флаттер может кэшировать и оптимизировать
- Потокобезопасность — нет race conditions
- Предсказуемость — состояние не меняется неожиданно
- Отладка — легче отслеживать изменения
- Тестирование — проще создавать test fixtures
Итого
Immutable объекты в Dart:
- Используют
finalдля всех полей - Используют
constконструкторы для оптимизации - Имеют методы
copyWith()для создания модифицированных копий - Критичны для правильного управления состоянием во Flutter
- Позволяют Флаттеру эффективнее определять изменения и перестраивать UI