Содержание

Типы функций в Solidity

Типы функций представлены в 2 вариантах: internal и external функции.

Internal-функции могут вызываться только внутри текущего контракта (точнее, внутри текущего блока кода, который также включает функции внутренних библиотек и унаследованные функции), потому что они не могут быть выполнены вне контекста текущего контракта.

External-функции состоят из адреса и сигнатуры функции, и они могут передаваться и возвращаться из внешних вызовов функций.

Типы функций записываются следующим образом:

function () {internal|external} [pure|constant|view|payable] [returns ()]

В отличие от параметров, возвращаемое значение не может быть пустым. Если тип функции ничего не возвращает, то вся чать returns (<return types>) отбрасывается.

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

Есть 2 способа получить доступ к функции в текущем контракте: либо прямо по ее имени f, либо используя this.f. Первый приведет к внутренней функции, а второй — к внешней.

Если переменная типа функции не инициализирована, ее вызов приведет к исключению. То же самое происходит, если вызывается функция после применения к ней delete.

Если внешние типы функций используются вне контекста Solidity, они рассматриваются как тип function, который кодирует адрес, сопровождаемый идентификатором функции, вместе в одном типе bytes24.

Public-функции текущего контракта могут использоваться как internal, так и external. Чтобы использовать f как internal-функцию, нужно просто использовать f, а если чтобы использовать external форму, нужно использовать this.f.

Вдобавок, публичные (или внешние) функции также имеют специальный член, называемый selector, который возвращает селектор функции ABI:

pragma solidity ^0.4.16;

contract Selector {
  function f() public view returns (bytes4) {
    return this.f.selector;
  }
}

Пример, показывающий, как использовать внутренние типы функций:

pragma solidity ^0.4.16;

library ArrayUtils {
  // internal-функции могут использоваться во внутренних библиотечных функциях,
  // потому что они будут частью одного и того же контекста кода
  function map(uint[] memory self, function (uint) pure returns (uint) f)
    internal
    pure
    returns (uint[] memory r)
  {
    r = new uint[](self.length);
    for (uint i = 0; i < self.length; i++) {
      r[i] = f(self[i]);
    }
  }
  function reduce(
    uint[] memory self,
    function (uint, uint) pure returns (uint) f
  )
    internal
    pure
    returns (uint r)
  {
    r = self[0];
    for (uint i = 1; i < self.length; i++) {
      r = f(r, self[i]);
    }
  }
  function range(uint length) internal pure returns (uint[] memory r) {
    r = new uint[](length);
    for (uint i = 0; i < r.length; i++) {
      r[i] = i;
    }
  }
}

contract Pyramid {
  using ArrayUtils for *;
  function pyramid(uint l) public pure returns (uint) {
    return ArrayUtils.range(l).map(square).reduce(sum);
  }
  function square(uint x) internal pure returns (uint) {
    return x * x;
  }
  function sum(uint x, uint y) internal pure returns (uint) {
    return x + y;
  }
}

Другой пример, который использует внешние типы функций:

pragma solidity ^0.4.11;

contract Oracle {
  struct Request {
    bytes data;
    function(bytes memory) external callback;
  }
  Request[] requests;
  event NewRequest(uint);
  function query(bytes data, function(bytes memory) external callback) public {
    requests.push(Request(data, callback));
    NewRequest(requests.length - 1);
  }
  function reply(uint requestID, bytes response) public {
    // Здесь идет проверка, что ответ приходит из надежного источника
    requests[requestID].callback(response);
  }
}

contract OracleUser {
  Oracle constant oracle = Oracle(0x1234567); // известный контракт
  function buySomething() {
    oracle.query("USD", this.oracleResponse);
  }
  function oracleResponse(bytes response) public {
    require(msg.sender == address(oracle));
    // Использовать данные
  }
}

Примечание

Встроенные функции планируются, но пока не поддерживаются.

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

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

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