Содержание

Using For в Solidity

Директива using A for B; используется, чтобы прикрепить функции библиотеки (из библиотеки A) к любому типу (B). Эти функции получат объект, который они вызывают, в качестве их первого параметра.

Эффект использования using A for *; состоит в том, что функции из библиотеки A прикрепляются к любому типу.

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

Директива using A for B; действует в текущей области видимости, которая ограничена контрактом на данный момент, но позже будет глобальная область видимости. Включив модуль, его типы данных, включая библиотечные функции, доступны без необходимости добавления дополнительного кода.

pragma solidity ^0.4.16;

library Set {
  struct Data { mapping(uint => bool) flags; }

  function insert(Data storage self, uint value)
      public
      returns (bool)
  {
      if (self.flags[value])
        return false;
      self.flags[value] = true;
      return true;
  }

  function remove(Data storage self, uint value)
      public
      returns (bool)
  {
      if (!self.flags[value])
          return false; // not there
      self.flags[value] = false;
      return true;
  }

  function contains(Data storage self, uint value)
      public
      view
      returns (bool)
  {
      return self.flags[value];
  }
}

contract C {
    using Set for Set.Data;
    Set.Data knownValues;

    function register(uint value) public {
        // Здесь все переменные типа Set.Data имеют
        // соответствующие функции члена.
        // Следующий вызов функции индентичен
        // `Set.insert(knownValues, value)`
        require(knownValues.insert(value));
    }
}

Можно расширить элементарные типы следующим способом:

pragma solidity ^0.4.16;

library Search {
    function indexOf(uint[] storage self, uint value)
        public
        view
        returns (uint)
    {
        for (uint i = 0; i < self.length; i++)
            if (self[i] == value) return i;
        return uint(-1);
    }
}

contract C {
    using Search for uint[];
    uint[] data;

    function append(uint value) public {
        data.push(value);
    }

    function replace(uint _old, uint _new) public {
        uint index = data.indexOf(_old);
        if (index == uint(-1))
            data.push(_new);
        else
            data[index] = _new;
    }
}

Все вызовы библиотеки — фактические вызовы функций EVM. Это означает, что, если передавать memory или типы значений, будет выполнена копия, даже из переменной self. Единственная ситуация, когда не происходит копирование, это использование ссылочных переменных хранилища.

Материал был полезен? Поделитесь в соц. сетях:
Логотип echain.ru

Добавить комментарий

Ваш e-mail не будет опубликован.