Ссылочные типы

Завершено

Для написания контрактов вам также потребуется понимать принципы использования ссылочных типов.

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

Расположение данных

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

  • memory:
    • Расположение, в котором хранятся аргументы функции.
    • Время существования ограничено жизненным циклом вызова внешней функции.
  • storage:
    • Расположение, в котором хранятся переменные состояния.
    • Время существования ограничено временем существования контракта.
  • calldata:
    • Расположение, в котором хранятся аргументы функции.
    • Это расположение требуется для параметров внешних функций, но может использоваться и для других переменных.
    • Время существования ограничено жизненным циклом вызова внешней функции.

Ссылочные типы всегда создают независимую копию данных.

Ниже приведен пример использования ссылочного типа:

contract C {

  uint[] x;
  
  // the data location of values is memory
  function buy(uint[] memory values) public {
      x = values; // copies array to storage
      uint[] storage y = x; //data location of y is storage
      g(x); // calls g, handing over reference to x
      h(x); // calls h, and creates a temporary copy in memory
  }

  function g(uint[] storage) internal pure {}
  function h(uint[] memory) public pure {}
}

Массивы

Массивы используются для хранения схожих данных в структуре набора данных. Размер массива может быть фиксирован или задаваться динамически. Индекс массива начинаются с 0.

Чтобы создать массив фиксированного размера k, содержащий элементы типа T, следует использовать выражение T[k]. Для массива с динамическим размером можно написать T[].

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

В следующем примере показано создание массива:

uint[] itemIds; // Declare a dynamically sized array called itemIds
uint[3] prices = [1, 2, 3]; // initialize a fixed size array called prices, with prices 1, 2, and 3
uint[] prices = [1, 2, 3]; // same as above

Элементы массива

Для управления массивами и получения сведений о них можно использовать следующие члены:

  • length — получение длины массива.
  • push() — добавление элемента в конец массива.
  • pop — удаление элемента с конца массива.

Ниже приведено несколько примеров:

// Create a dynamic byte array
bytes32[] itemNames;
itemNames.push(bytes32("computer")); // adds "computer" to the array
itemNames.length; // 1

Структуры

Структуры — это настраиваемые типы, с помощью которых пользователь может определять представление реальных объектов. Как правило, структуры используются в качестве схемы или для представления записей.

Пример объявления структуры:

struct Items_Schema {
    uint256 _id;
    uint256 _price;
    string _name;
    string _description;
}

Типы сопоставления

Сопоставления представляют собой пары из ключа и значения, которые инкапсулируются или упаковываются вместе. Ближайшими аналогами сопоставлений являются словари или объекты JavaScript. Как правило, сопоставления используются для моделирования реальных объектов и более быстрого поиска данных. В частности, значениями могут быть сложные типы, такие как структуры, обеспечивающие гибкость и удобочитаемость типа сопоставления.

В следующем примере кода используется структура Items_Schema и сохраняется словарь со списком элементов, представленных структурой Items_Schema. Таким образом, с помощью сопоставлений можно имитировать базу данных.

contract Items {
    uint256 item_id = 0;

    mapping(uint256 => Items_Schema) public items;

    struct Items_Schema {
      uint256 _id:
      uint256 _price:
      string _name;
    }

    function listItem(uint256 memory _price, string memory _name) public {
      items[item_id] = Items_Schema(item_id, _price, _name);
      item_id += 1;
    }
}

Примечание.

В сигнатуре сопоставления uint256 => Items_Schema указывается, что ключи имеют целочисленный тип без знака, а значения являются типом структуры Items_Schema.