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

Как устроен redirecting constructor?

1.7 Middle🔥 141 комментариев
#Dart

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

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

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

Как устроен redirecting constructor?

Redirecting constructor (перенаправляющий конструктор) в Dart — это конструктор, который не выполняет собственный код, а делегирует всю инициализацию другому конструктору того же класса. Это мощный инструмент для уменьшения дублирования и централизации логики инициализации.

Основной синтаксис

Перенаправляющий конструктор использует двоеточие и двоеточие (:) с вызовом другого конструктора:

class Point {
  int x = 0;
  int y = 0;

  // Основной конструктор
  Point(this.x, this.y);

  // Перенаправляющий конструктор
  Point.origin() : this(0, 0);
  
  // Ещё один redirect
  Point.clone(Point other) : this(other.x, other.y);
}

void main() {
  var p1 = Point(5, 10);
  var p2 = Point.origin();      // (0, 0)
  var p3 = Point.clone(p1);     // (5, 10)
}

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

Пример 1: Различные способы создания объекта

class Rectangle {
  double width;
  double height;

  // Основной конструктор
  Rectangle(this.width, this.height);

  // Создание квадрата
  Rectangle.square(double size) : this(size, size);

  // Создание с дефолтными значениями
  Rectangle.defaultSize() : this(100, 100);

  // Копирование
  Rectangle.copy(Rectangle other) : this(other.width, other.height);

  double get area => width * height;
}

void main() {
  var rect1 = Rectangle(10, 20);
  var rect2 = Rectangle.square(15);
  var rect3 = Rectangle.copy(rect1);
}

Пример 2: Валидация перед redirect

class User {
  String name;
  int age;

  User(this.name, this.age);

  User.fromEmail(String email) : this(email.split("@")[0], 18);

  User.adult(String name, int age) : this(name, age > 18 ? age : 18);
}

Цепочка перенаправлений

Перенаправления могут быть цепочкой, но только вниз по иерархии конструкторов:

class Configuration {
  String host;
  int port;
  bool ssl;
  String? proxy;

  // Основной конструктор
  Configuration(this.host, this.port, this.ssl, this.proxy);

  // Redirect 1
  Configuration.http(String host) : this(host, 80, false, null);

  // Redirect 2 -> перенаправляется на redirect 1
  Configuration.httpLocal() : this.http("localhost");

  // Redirect 3
  Configuration.https(String host) : this(host, 443, true, null);
}

void main() {
  var local = Configuration.httpLocal();  // -> http -> основной
  var prod = Configuration.https("api.example.com");
}

Отличие от super()

Без redirecting constructor нужно было бы дублировать инициализацию:

// БЕЗ redirect (плохо - дублирование)
class Point {
  int x = 0;
  int y = 0;

  Point(this.x, this.y);
  
  // Сложно поддерживать, есть дублирование
  Point.origin() {
    x = 0;
    y = 0;
  }
}

// С redirect (хорошо - DRY)
class Point {
  int x = 0;
  int y = 0;

  Point(this.x, this.y);
  
  Point.origin() : this(0, 0);  // Чистый и понятный код
}

Ограничения

  • Перенаправляющий конструктор не может иметь тело (даже пустое)
  • Нельзя вызывать super() в redirecting constructor
  • Нельзя инициализировать поля напрямую — только через redirect
// ✗ Ошибка
Point.bad() : this(0, 0) { } 

// ✗ Ошибка
Point.bad() : x = 0, this(0, 0);

// ✓ Правильно
Point.good() : this(0, 0);

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

  • Множественные способы создания объекта
  • Дефолтные значения для аргументов
  • Валидация перед инициализацией
  • Копирование объектов
  • Фасад для сложной инициализации

Perendirekting constructor — это элегантный способ избежать дублирования кода инициализации и сделать API класса более удобным для использования.

Как устроен redirecting constructor? | PrepBro