Dart 3.0 предлагает расширенные возможности

Dart 3.0 Records — это здорово, но зачем они вообще нужны?

Dart 3.0 и Flutter 3.10 обладают тремя великими возможностями: записью, шаблонами и модификаторами классов. Но почему и как?

Dart 3.0 анонсирован на Google IO 2023 с некоторыми интересными функциями, такими как:

В этой статье я хочу рассказать только о рекордах (остальные я расскажу позже)

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

Проблема

Предположим, нам нужна только информация о местоположении.

Как мы собираемся получить x, y или даже z?

Без какого-либо решения это будет выглядеть так;

double getXLocation() {
  return 0;
}

double getYLocation() {
  return 0;
}

void noSolution() {
  final x = getXLocation();
  final y = getYLocation();
  final z = getZLocation(); // Exception: no getZLocation() method!!
}

Мы должны получить x и y отдельно, но это приведет к более подробному коду. но в хорошем смысле он по-прежнему типобезопасен, и мы по-прежнему получаем ошибки времени компиляции.

Давайте посмотрим на решения и их проблемы.

Решение 1. Использование списка

Если мы можем вернуть только одну вещь, то мы можем поместить значения в список и отправить их обратно, верно?

List<double> getlocation() {
  return [0, 0]; // We can't be sure which one is x or y.
}

void usingList() {
  final location = getlocation();
  final x = location[0]; // What does 0 stand for?
  final y = location[1]; // what does 1 stand for?
  final z = location[2]; // Exception!! Not in inclusive range blah..blah
}

Несмотря на то, что это решает проблему, с ним тоже есть некоторые проблемы.

  • Мы не знаем, что они означают.
    Что такое 0 и 0? Это х и у или у и х? или даже x и z, может быть?
  • Мы не знаем, сколько параметров он возвращает.
    Есть ли аргумент Z или около того?

Хуже всего то, что мы можем не заметить ошибки во время выполнения в этот момент, но пользователи обязательно заметят!

Какая катастрофа!

Решение 2. Использование карты

Мы также можем использовать Map для решения запутанных параметров.
Просто укажите их имена как x и y, и все готово!

Map<String, double> getlocation() {
  return {'x': 0, 'y': 0}; // We know what x and y are now. Yayy!
}

void usingMap() {
  final location = getlocation();
  final x = location['x'];
  final y = location['t']; // Ooppps!! Typo!
  final z = location['z']; // No error but gives us null :/
}

Но в это время,

  • У нас нет ошибки времени выполнения, но теперь мы можем получить нулевые параметры.
  • Мы до сих пор не знаем, какие опции мы получаем от метода.
    Есть ли аргумент Z или нет и т. д.
  • Это небезопасно для типов
    Мы можем случайно написать ['t'] вместо ['y'].

Решение 3. Использование класса

Это было мое любимое решение.
Мы создаем класс, который нам нужен, как мы хотим, и используем его без каких-либо хлопот.

class Location {
  final double x;
  final double y;

  const Location({required this.x, required this.y});
}

Location getlocation() {
  return Location(x: 0, y: 0);
}

void usingClass() {
  final location = getlocation();
  final x = location.x;
  final y = location.y;
  final z = location.z; // Compile-time error, yayy!!
}

Но нам всегда нужно определить класс и выполнить дополнительную работу только для простой задачи, а мне иногда лень это делать.

Вот почему, несмотря на то, что мне нравится такой подход, я не люблю прилагать дополнительные усилия для одновременного возврата нескольких переменных.

Так что проблема здесь,

  • Довольно утомительно писать новый класс каждый раз, когда он нам нужен.

Решение 4. Использование универсального класса (AKA Dart’s Tuples)

Да! Мы можем использовать общие классы, чтобы решить эту проблему!

class Tuple<T1, T2> {
  final T1 x;
  final T2 y;

  const Tuple({required this.x, required this.y});
}

Tuple<double, double> getlocationAsDouble() {
  return Tuple(x: 0,y: 0);
}

// Alternatively
Tuple<String, String> getlocationAsString() {
  return Tuple(x: '0', y: '0');
}

void usingGenericClass() {
  final location = getlocationAsDouble();
  final location2 = getlocationAsString(); // Alternatively

  final x = location.x;
  final y = location.y;
  final z = location.z;
}

Мы можем сгенерировать столько кортежей, сколько захотим!

Нет необходимости создавать классы каждый раз.

но в это время,

  • Нам нужно создать несколько предопределенных кортежей.
    Tuple2(x,y), Tuple3(x,y,z); и т. д.
  • Получение аргументов может привести к написанию дополнительных строк
    final x = location.x;
    final y = location.y;
    final z = location.z;

(Окончательное) Решение 5: Записи

Записи — это, по сути, новый тип данных, который позволяет нам создавать анонимные, неизменяемые списки фиксированного размера.

Синтаксис очень похож на круглые скобки функции, но как тип данных.

(double x, double y) getlocation() {
  return (0, 0);
}

void usingUnnamedRecord() {
  final (x, y) = getlocation(); // That's it!

  // alternatively
  final location = getlocation();
  final x = location.$1;
  final y = location.$2;
}

Как видите, теперь у нас есть чистый и простой код.

  • Нет непредвиденных ошибок во время выполнения
  • Нет шаблонного/подробного кода
  • Нет проблем с нулевым значением
  • Никаких запутанных/магических чисел

Все отлично, но $1 и $2 выглядят довольно уродливо, не так ли?

К счастью, мы можем избавиться от них, используя записи с именованными параметрами.

({double x, double y}) getlocation() {
  return (x: 0, y: 0);
}

void usingNamedRecord() {
  final (:x, :y) = getlocation(); // shorter version of (x:x, y:y)

  // alternatively
  final location = getlocation();
  final x = location.x;
  final y = location.y;

  // we can also rename them too!
  final (x: myX, y: myY) = getlocation(); // rename while assigning
  print('$myX, $myX');
}

Теперь мы можем получить x и y, как захотим.

Вот и все!

Спасибо, что дочитали до сих пор!

Это было мое путешествие с пластинками. Я надеюсь, что это будет полезно и для вас!

Напоследок, хлопаем в ладоши 👏 Запись на эту статью! :)))

Вы можете подписаться на меня и быть в курсе новых частей!

Также, пожалуйста, не забывайте поддерживать мои статьи моей реферальной ссылкой!

Имейте трепетный день!