Ответ
Redirecting constructor (перенаправляющий конструктор) в Dart — это конструктор, который не имеет собственного тела и списка инициализаторов, а лишь перенаправляет вызов на другой конструктор того же класса с помощью синтаксиса : this(...). Это позволяет создавать удобные фабричные методы или альтернативные способы инстанцирования объекта без дублирования кода.
Синтаксис и пример:
class Rectangle {
final double width;
final double height;
final String label;
// Основной конструктор
Rectangle(this.width, this.height, [this.label = 'Rectangle']);
// Redirecting конструктор для создания квадрата.
// Он просто вызывает основной конструктор, подставляя height = width.
Rectangle.square(double sideLength) : this(sideLength, sideLength, 'Square');
// Ещё один redirecting конструктор с преобразованием параметров.
Rectangle.fromMap(Map<String, double> dimensions)
: this(dimensions['width'] ?? 0.0, dimensions['height'] ?? 0.0);
}
void main() {
final rect = Rectangle(10, 20);
final square = Rectangle.square(15); // Вызовет Rectangle(15, 15, 'Square')
final fromMap = Rectangle.fromMap({'width': 5, 'height': 7});
}
Ключевые особенности:
- Нет тела: После двоеточия (
:) может быть только вызовthis(...). - Нет initializer list: Нельзя использовать
: width = 10, height = 20. - Цель — избежать дублирования: Вся логика инициализации сосредоточена в основном конструкторе.
- Удобство для API: Позволяет предоставить пользователю класса более интуитивно понятные имена методов создания (например,
Point.polar(radius, angle)).
Ответ 18+ 🔞
Ёпта, слушай, вот есть у тебя класс, как будто чертёж для создания штук. И конструктор — это такой спецметод, который из этого чертежа реальную хрень делает. Так вот, иногда хочется сделать штуку по-разному, но чтобы внутри всё равно собиралось одним проверенным способом, без копипасты кода, который потом поддерживать — пиздец.
Вот смотри, представь, что у тебя класс Rectangle — прямоугольник. У него есть ширина, высота и, допустим, какая-нибудь подпись.
class Rectangle {
final double width;
final double height;
final String label;
// Вот это наш главный, основной конструктор. Он всё умеет.
Rectangle(this.width, this.height, [this.label = 'Rectangle']);
}
Всё чётко. Но потом тебе в голову приходит: «А дай-ка я сделаю удобный способ создавать квадраты!». Квадрат — это же прямоугольник, у которого ширина и высота одинаковые. И терпения ноль ебать писать каждый раз Rectangle(15, 15, 'Square').
Можно, конечно, накостылить отдельный метод, но зачем, если в Dart есть redirecting constructor — перенаправляющий конструктор. Это такая хитрая жопа, у которой нет своего тела. Вообще. Она только говорит: «Эй, чувак, иди нахуй, вернись к главному конструктору и скажи ему собрать объект вот с такими параметрами».
Вот как это выглядит:
class Rectangle {
final double width;
final double height;
final String label;
Rectangle(this.width, this.height, [this.label = 'Rectangle']);
// А вот и он! Redirecting constructor для квадрата.
// Видишь двоеточие и this(...)? Всё. Больше ничего.
// Он берёт sideLength и говорит главному конструктору:
// «Собери прямоугольник, где width = sideLength, height = sideLength, label = 'Square'».
Rectangle.square(double sideLength) : this(sideLength, sideLength, 'Square');
}
И теперь в коде просто пишешь:
final mySquare = Rectangle.square(10); // Вжух! И создался Rectangle(10, 10, 'Square')
Ещё пример, чтобы вообще всё стало ясно, как божий день. Допустим, тебе данные приходят в виде мапы (JSON там какой-нибудь). Тоже не хочется руками распаковывать:
class Rectangle {
// ... поля те же ...
Rectangle(this.width, this.height, [this.label = 'Rectangle']);
Rectangle.square(double sideLength) : this(sideLength, sideLength, 'Square');
// И ещё один redirecting constructor! Из мапы.
// Берёт мапу, выковыривает оттуда 'width' и 'height' (или 0.0, если нихуя нет),
// и — бац! — передаёт это всё в основной конструктор.
Rectangle.fromMap(Map<String, double> dimensions)
: this(dimensions['width'] ?? 0.0, dimensions['height'] ?? 0.0);
}
А теперь главные правила, чтобы не обосраться:
- Никакого тела. После
: this(...)точка с запятой и всё. Нельзя написать{ print('hello'); }— будет тебе хиросима и нигерсраки в виде ошибки компиляции. - Никакого своего списка инициализации. Только вызов
this(...). Нельзя написать: width = 10, this(10, 20). - Вся сила — в основном конструкторе. Redirecting-конструктор — это просто красивый фасад, дверь, которая ведёт в одну и ту же комнату. Вся настоящая работа (проверки, присваивания final-полям) делается там, куда он перенаправляет.
- Удобство для тех, кто будет этим пользоваться. Вместо того чтобы дергать в коде
Rectangle(15, 15, 'Square'), можно дать людям понятныйRectangle.square(15). И доверия ебать больше, и в документации красивее.
Короче, redirecting constructor — это как если бы ты, вместо того чтобы самому лезть в холодильник за пивом, сказал корегу: «Слушай, принеси-ка мне из холодильника пивасика». Он делает всю грязную работу (открывает дверцу, ищет), а ты получаешь готовый результат. Удобно, ёпта.