← Назад к вопросам

Что такое with в Dart?

1.0 Junior🔥 142 комментариев
#Dart

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

With в Dart — примеси (Mixins)

With — это ключевое слово в Dart для подключения примесей (mixins) к классам. Mixin позволяет переиспользовать код из одного или нескольких классов без наследования.

Основная идея

Mixin решает проблему множественного наследования, позволяя:

  • Переиспользовать функциональность без создания иерархии наследования
  • Комбинировать поведение из нескольких источников
  • Избежать дублирования кода между разными классами
  • Сохранить чистоту архитектуры — не создавать лишние базовые классы

Синтаксис

class MyClass extends SomeClass with Mixin1, Mixin2 {}

Определение Mixin

// Способ 1: mixin ключевое слово (рекомендуется)
mixin Drawable {
  void draw() {
    print('Drawing...');
  }
}

// Способ 2: abstract class (старый способ)
abstract class Drawable {
  void draw() {
    print('Drawing...');
  }
}

Практические примеры

Использование Mixin для общей функциональности:

mixin Loggable {
  void log(String message) {
    print('[LOG] $message');
  }
}

mixin Validatable {
  bool validate(String input) {
    return input.isNotEmpty;
  }
}

class User with Loggable, Validatable {
  String name = '';

  void setName(String input) {
    if (validate(input)) {
      name = input;
      log('Name set to $input');
    }
  }
}

final user = User();
user.setName('John');
// Output: [LOG] Name set to John

Flutter пример: State Management Mixin

mixin LoadingMixin {
  bool _isLoading = false;
  bool get isLoading => _isLoading;

  Future<T> withLoading<T>(Future<T> Function() action) async {
    _isLoading = true;
    try {
      return await action();
    } finally {
      _isLoading = false;
    }
  }
}

class UserProvider with ChangeNotifier, LoadingMixin {
  Future<void> fetchUser() async {
    await withLoading(() => Future.delayed(Duration(seconds: 2)));
    notifyListeners();
  }
}

Mixin с параметрами типа (Generics):

mixin Cache<T> {
  T? _cachedValue;

  T? get cached => _cachedValue;
  
  void setCached(T value) {
    _cachedValue = value;
  }

  void clearCache() {
    _cachedValue = null;
  }
}

class UserRepository with Cache<User> {
  Future<User> getUser(String id) async {
    // Проверяем кэш
    if (cached != null) return cached!;

    // Запрашиваем данные
    final user = await _fetchFromApi(id);
    setCached(user);
    return user;
  }

  Future<User> _fetchFromApi(String id) async {
    // API call
    return User(id: id, name: 'John');
  }
}

Mixin с ограничениями (on keyword):

abstract class Animal {
  void move();
}

// Этот mixin может использоваться только с классами, наследующими Animal
mixin Swimable on Animal {
  void swim() {
    print('Swimming...');
  }
}

class Duck extends Animal with Swimable {
  @override
  void move() => print('Walking...');
}

final duck = Duck();
duck.move();  // Walking...
duck.swim();  // Swimming...

Порядок поиска методов (MRO)

class A {
  void test() => print('A');
}

mixin M1 {
  void test() => print('M1');
}

mixin M2 {
  void test() => print('M2');
}

class B extends A with M1, M2 {}

B().test(); // Output: M2
// Порядок поиска: B → M2 → M1 → A

Когда использовать With

  • Повторяющаяся функциональность — логирование, кэширование, валидация
  • State Management — ChangeNotifier mixins в Flutter
  • Поведение на уровне приложения — loading states, error handling
  • Разделение ответственности — логика в отдельных mixins

Разница между наследованием и With

Наследование (extends):

  • Создает иерархию классов
  • Один родительский класс
  • Может переопределять поля

Примесь (with):

  • Просто добавляет функциональность
  • Можно несколько mixins
  • Не может переопределять поля (только методы)

With в Dart — это элегантный способ переиспользовать код без лишней сложности иерархии наследования.