Кортежи records

Последнее обновление: 13.05.2023

Начиная с версии 3.0 в языке Dart появилась такая возможность как records. Records являются анонимным, неизменяемым типом, который, подобно типам коллекций, позволяет объединять несколько объектов в один объект. В отличие от других типов коллекций, records имеют фиксированный размер, могут хранить значения разных типов и типизированы. В других языках программирования есть аналогичная структура данных - кортежи

Например, определим простейший кортеж:

void main() {

  var person = ("Tom", 38);
  print(person);    // ("Tom", 38)
}

Здесь определен кортеж person, который состоит из двух элементов - строки "Tom" и целого числа 38. Для определения кортежа применяются круглые скобки, внутри которых через запятую перечисляются элементы кортежа. Мы можем вывести содержимого этого кортежа с помощью функции print.

Стоит отметить, что кортежи - типизированы, они имеют определенный тип, который определяет, данные каких типов и в какой последовательности имеются в кортеже. Так, в примере выше для определения кортежа применялось ключевое слово var, при котором тип кортежа выводился автоматически исходя из присваемого значения. Но мы также можем явным образом указать тип:

void main() {

  (String, int) person = ("Tom", 38);
  print(person);
}

Кортеж ("Tom", 38) представляет тип (String, int). Тип кортежа также определяется с помощью кавычек, внутри которых указываются типы вложеннных элементов. Причем порядок имеет значение. Так, тип (String, int) указывает, что вначале в кортеже должна идти строка и только потом число, а не наоборот. Например, следующее определение кортежа будет ошибочным:

(String, int) person = (22, "Tom");  // ! Ошибка

Подобным образом можно определять кортежи с большим количеством элементов. Например:

void main() {

  (String, int, String) person = ("Tom", 38, "Google");
  print(person);
}

Обращение к элементам кортежа

По умолчанию для обращения к элементам кортежа используются номера элементов в кортеже, которые предваряются символом $ (нумерация начинается с 1):

void main() {

  var person = ("Tom", 38);
  print(person.$1);   // Tom
  print(person.$2);   // 38
}

Например, выражение person.$1 представляет обращение к первому элементу кортежа person, а person.$2 - к второму элементу.

Но также для каждого элемента кортежа можно указать имена:

void main() {

  var person = (name:"Tom", age:38);
  print(person.name);   // Tom
  print(person.age);   // 38
}

В этом случае сначала указывается имя и через двоеточие значение элемента. Стоит отметить, что в этом случае тип кортежа будет ({int age, String name}):

void main() {

  ({int age, String name}) person = (name:"Tom", age:38);
  print(person.name);   // Tom
  print(person.age);   // 38
}

И в случае с именованными элементами их порядок роли не играет. Можно комбинировать именованные и анонимные элементы, но в этом случае именованные элементы идут после анонимных:

void main() {

  var person = ("Tom", age:38);
  print(person.$1);   // Tom
  print(person.age);   // 38
}

Применение кортежей

Рассмотрим сценарии, где кортежи нам могут пригодиться. Традиционно функции в языке Dart могли возвращать только одно значение. Если же надо было возвратить из функции несколько значений, то их надо было либо упаковывать их в другие типы данных, например, в списки, либо определять новые классы, которые могли бы хранить подобные множественные значения. И кортежи как раз позволяют решить эту проблему:

void main() {

  var person = defaultPerson();
  print(person);  // ("Tom", 22)
}

(String, int) defaultPerson(){
  
  return ("Tom", 22);
}

Здесь для простоты функция defaultPerson просто возвращает кортеж из двух элементов. В функции main результат функции defaultPerson можно присвоить переменной person.

Также можно возвращать кортеж с именованными элементами:

void main() {

  var person = defaultPerson();
  print(person.name);  // ("Tom", 22)
}

({String name, int age}) defaultPerson(){
  
  return (name:"Tom", age:22);
}

Еще один сценарий представляет передачу в функцию множества значений. И опять же здесь мы можем объединить все значения в кортеж:

void main() {

  createPerson(("Bob", 42));
}

void createPerson((String, int) data){
  print("Name: ${data.$1}");
  print("Age: ${data.$2}");
}

Передача кортежа с именованными элементами:

void main() {

  createPerson((name:"Sam", age:27));
}

void createPerson(({String name, int age}) data){
  print("Name: ${data.name}");
  print("Age: ${data.age}");
}

Сравнение кортежей

Кортежи сравниваются поэлементно в порядке следования элементов:

void main() {

  var person = ("Tom", 38);
  var tom = ("Tom", 38);
  var tomas = (name:"Tom", age:38);

  print(person == tom);     // true
  print(person == tomas);   // false
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850