Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Нововведения Dart 3.0 в практике
Основные фичи Dart 3.0
Дарт 3.0 принёс значительные улучшения в язык. Я активно использую несколько ключевых нововведений в своих проектах.
1. Records и Pattern Matching
Это мощная фича для работы со сложными данными структурами.
Records — неименованные кортежи с типизацией:
// Вместо отдельного класса или Tuple
Record myData = (int: 42, String: 'Hello', bool: true);
// С типизацией
(int, String, bool) data = (10, 'World', false);
// Доступ к полям
print(data.$1); // 10
print(data.$2); // 'World'
// Именованные поля в records
({int age, String name, bool active}) person = (
age: 25,
name: 'John',
active: true,
);
print(person.age); // 25
print(person.name); // 'John'
Pattern Matching — мощная деструктуризация:
// Вместо множества if/else
void processUser((int id, String name, String email) user) {
final (id, name, email) = user;
print('User $id: $name ($email)');
}
// В switch statements
switch (user) {
case (int id, String name, _):
print('Valid user: $name');
case (_, _, String email) when email.contains('@'):
print('Valid email: $email');
default:
print('Invalid user data');
}
// В функциях с guard clauses
String getUserStatus((int age, String name) person) => switch (person) {
(var age, var name) when age >= 18 => '$name is an adult',
(var age, var name) => '$name is a minor',
};
2. Sealed Classes — безопасные иерархии
Отличная замена для type-safe перечисления статусов и событий.
// Определяем sealed класс
sealed class ApiResponse {
const ApiResponse();
}
// Подклассы — единственный способ расширить
class Success extends ApiResponse {
final dynamic data;
Success(this.data);
}
class Error extends ApiResponse {
final String message;
Error(this.message);
}
class Loading extends ApiResponse {
const Loading();
}
// Компилятор проверит, что мы обработали ВСЕ случаи
String handleResponse(ApiResponse response) => switch (response) {
Success(:final data) => 'Success: $data',
Error(:final message) => 'Error: $message',
Loading() => 'Loading...',
// Если забыть case — ошибка компиляции!
};
3. Enhanced Enums с членами
enum DatabaseOperation {
create('INSERT'),
read('SELECT'),
update('UPDATE'),
delete('DELETE');
final String sql;
const DatabaseOperation(this.sql);
String toQuery(String table) => '$sql FROM $table';
}
// Использование
print(DatabaseOperation.create.sql); // 'INSERT'
print(DatabaseOperation.read.toQuery('users')); // 'SELECT FROM users'
4. Extension Types — zero-cost абстракции
Лёгкие обёртки над типами без оверхеда.
// Создаём type-safe обёртку над String для ID
extension type UserId(String value) {
bool get isValid => value.isNotEmpty && value.length > 5;
String toUpperCase() => value.toUpperCase();
}
// Использование
final id = UserId('abc123def');
if (id.isValid) {
print(id.toUpperCase()); // ABC123DEF
}
// Предотвращает случайное перепутывание ID типов
void processUser(UserId userId) {
// Принимает только UserId, не просто String
}
final stringId = 'some-id';
processUser(stringId); // ❌ Ошибка компиляции!
processUser(UserId(stringId)); // ✅ OK
5. Augmentation (Preview) — метапрограммирование
Для код-генерации и AOP без полной зависимости от build_runner в некоторых случаях.
// В файле model.dart
class User {
final String name;
final int age;
User(this.name, this.age);
}
// В файле model.augment.dart
augment library 'model.dart';
augment class User {
@override
String toString() => 'User(name: $name, age: $age)';
bool get isAdult => age >= 18;
}
Практическое применение в приложении
// Объединяем несколько фич для надёжного обработчика данных
sealed class ApiResult<T> {
const ApiResult();
}
final class ApiSuccess<T> extends ApiResult<T> {
final T data;
const ApiSuccess(this.data);
}
final class ApiError<T> extends ApiResult<T> {
final String message;
final int? statusCode;
const ApiError(this.message, {this.statusCode});
}
final class ApiLoading<T> extends ApiResult<T> {
const ApiLoading();
}
// Использование с pattern matching
Widget buildApiWidget(ApiResult<List<User>> result) {
return switch (result) {
ApiSuccess(:final data) => UserListView(users: data),
ApiError(:final message, :final statusCode) => ErrorView(
message: message,
statusCode: statusCode,
),
ApiLoading() => const LoadingSpinner(),
};
}
// Type-safe repository
extension type UserId(String value) {
bool get isValid => value.isNotEmpty;
}
extension type SessionToken(String value) {}
class AuthRepository {
Future<ApiResult<SessionToken>> login(String email, String password) async {
try {
// логика
return ApiSuccess(SessionToken(token));
} catch (e) {
return ApiError('Login failed', statusCode: 401);
}
}
}
Почему это важно
Преимущества Dart 3.0 фич:
- Type Safety — компилятор ловит больше ошибок на этапе компиляции
- Readability — код с patterns намного понятнее множества if/else
- Productivity — меньше boilerplate, больше фокуса на логике
- Performance — extension types имеют zero-cost abstraction
- Refactoring — sealed classes гарантируют, что я обновлю все switch cases
Эти фичи делают Dart более выразительным языком и позволяют писать более надёжный, читаемый код.