Использование структур, массивов и отображений в полной мере

Введение

Массивы — один из самых популярных типов данных в объектно-ориентированном программировании. По определению, массив — это тип данных, который хранит внутри себя несколько переменных других типов данных. В типичном объектно-ориентированном программировании массивы действительно эффективны, потому что они также могут хранить массивы внутри себя почти до бесконечности. Массивы внутри массивов, называемые вложенными массивами, являются прекрасным представлением реальных данных.

Однако Solidity не является настоящим объектно-ориентированным языком (он ориентирован на контракты), и его массивы определяются по-другому. Во-первых, массивы в Solidity могут принимать переменные только одного предопределенного типа данных. Таким образом, массив uint может принимать только значения uint, массив строк может принимать только строковые переменные и т. д. И массивы Solidity, конечно, не могут содержать внутри себя другие массивы. Вложенные массивы невозможны. Таким образом, у программиста, переходящего с Java, Python или JavaScript на Solidity, возникает один из неотложных вопросов: как реализовать массивы, содержащие массивы, для создания хорошо структурированных сетевых метаданных? Что ж, ответ прост. Мы объединяем два уникальных для Solidity типа данных, называемых отображениями и структурами, с массивами.

Что такое структура?

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

struct People {
    string name;
    uint height_in_cm;
    bytes gender;
}
People memory yours_truly = People("Peter Ogwara", 155, "m");

Таким образом, объявление структуры просто дает форму, из которой могут быть созданы ее экземпляры, такие как yours_tuly выше.

Что такое картографирование?

Отображение — это тип данных, который позволяет компенсировать экземпляры одного типа данных другим. Например, uint, представляющий уникальный идентификатор пользователя, может быть связан с адресом или строка, представляющая имя, с uint, представляющим возраст. Токены ERC используют этот тип данных для записи баланса токенов каждого адреса. Сопоставления объявляются и устанавливаются таким образом:

mapping(uint=>string) user_id_to_username;
uint id = 1;
user_id_to_username[id] = "peterogwara";

Чтобы вызвать информацию в отображении, все, что нужно, — это значение первой переменной. Например, чтобы использовать приведенное выше сопоставление для получения имени пользователя с идентификатором 1, мы должны сделать следующее.

uint id = 1;
username = user_id_to_username[id] //This will return "peterogwara"

Объединение массивов и отображений со структурами

А вот и самое интересное. Структуры и отображения можно комбинировать! Чтобы создать вложенный массив на один уровень глубины, мы можем создать сопоставление любого примитивного типа данных со структурой. Продолжая структуру People, определенную выше, и идею уникального идентификатора, вот пример:

mapping(uint=>People) user_id_to_details;

Затем уникальный идентификатор можно было бы использовать для вызова гораздо большего количества деталей, чем одно имя пользователя. Конечно, в структуру можно добавить любое количество переменных, чтобы сделать ее более полной при определении человека. Обратите внимание, что отображение включает конкретное имя структуры (People), а не просто «struct».

Углубление на большем уровне

Однако предположим, что мы хотим включить список технологий каждого человека и сведения об их домашних кошках в их сведениях. Мы должны пройти дополнительный уровень вглубь. Этого можно добиться, объявив массив строк для стека технологий в структуре people. К сожалению, мы не можем включать структуру внутри структуры или вложенное отображение внутри структуры. Однако мы можем создавать отдельные структуры для той же цели и использовать массивы в исходной структуре для их отслеживания, таким образом создавая структуру CatDetails и массив CatDetails внутри структуры People. Наш код будет выглядеть примерно так:

uint userCount;
string[] _techstack;
CatDetails[] _cats;
struct People {
    string name;
    uint height;
    bytes gender;
    string[] tech_stack;
    CatDetails[] cats;
}
struct CatDetails {
    string name;
    uint age;
    string color;
}
mapping (uint=>People) user_id_to_details;

Затем можно было бы установить значения переменных, сначала объявив самый внутренний массив и установив его значения, а затем проделав то же самое для структуры на самом внешнем уровне. Глобальные массивы, объявленные в начале контракта, обеспечивают место хранения для объявлений в функциях, на которые указывают.

function setUser() public {
    uint userId = userCount++;
    string[] storage my_techstack = _techstack;
    my_techstack.push("Python");
    my_techstack.push("JavaScript");
    my_techstack.push("Solidity");
    CatDetails[] storage cats = _cats;
    CatDetails memory firstcat = CatDetails("Snuffles", 3, 'white');
    cats.push(firstcat);
        CatDetails memory secondcat = CatDetails("Garfield", 5, 'orange');
    cats.push(secondcat);
People memory yours_truly = People("Peter M. Ogwara", 155, "m", my_techstack, cats);
    user_id_to_details[userId] = yours_truly;
}

И точно так же у нас есть вложенные массивы/структуры! Вызов данных довольно прост и выполняется в обычном формате вызова сопоставления/структуры/массива. Например, строка ниже вернет имя второго кота пользователя №1.

return user_id_to_details[1].my_cats[1].name;

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

🌟 Не стесняйтесь задавать вопросы! 🌟

Подпишитесь на меня, чтобы узнать больше о Blockchain, Javascript, PHP, Python или чистом программировании.

Средний | Твиттер | Github | Amazon

Новичок в трейдинге? Попробуйте криптотрейдинговых ботов или копи-трейдинг