diff options
Diffstat (limited to 'docs/contracts')
-rw-r--r-- | docs/contracts/visibility-and-getters.rst | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst new file mode 100644 index 00000000..e78c9674 --- /dev/null +++ b/docs/contracts/visibility-and-getters.rst @@ -0,0 +1,198 @@ +.. index:: ! visibility, external, public, private, internal + +.. _visibility-and-getters: + +********************** +Visibility and Getters +********************** + +Since Solidity knows two kinds of function calls (internal +ones that do not create an actual EVM call (also called +a "message call") and external +ones that do), there are four types of visibilities for +functions and state variables. + +Functions have to be specified as being ``external``, +``public``, ``internal`` or ``private``. +For state variables, ``external`` is not possible. + +``external``: + External functions are part of the contract interface, + which means they can be called from other contracts and + via transactions. An external function ``f`` cannot be called + internally (i.e. ``f()`` does not work, but ``this.f()`` works). + External functions are sometimes more efficient when + they receive large arrays of data. + +``public``: + Public functions are part of the contract interface + and can be either called internally or via + messages. For public state variables, an automatic getter + function (see below) is generated. + +``internal``: + Those functions and state variables can only be + accessed internally (i.e. from within the current contract + or contracts deriving from it), without using ``this``. + +``private``: + Private functions and state variables are only + visible for the contract they are defined in and not in + derived contracts. + +.. note:: + Everything that is inside a contract is visible to + all observers external to the blockchain. Making something ``private`` + only prevents other contracts from accessing and modifying + the information, but it will still be visible to the + whole world outside of the blockchain. + +The visibility specifier is given after the type for +state variables and between parameter list and +return parameter list for functions. + +:: + + pragma solidity >=0.4.16 <0.6.0; + + contract C { + function f(uint a) private pure returns (uint b) { return a + 1; } + function setData(uint a) internal { data = a; } + uint public data; + } + +In the following example, ``D``, can call ``c.getData()`` to retrieve the value of +``data`` in state storage, but is not able to call ``f``. Contract ``E`` is derived from +``C`` and, thus, can call ``compute``. + +:: + + pragma solidity >=0.4.0 <0.6.0; + + contract C { + uint private data; + + function f(uint a) private pure returns(uint b) { return a + 1; } + function setData(uint a) public { data = a; } + function getData() public view returns(uint) { return data; } + function compute(uint a, uint b) internal pure returns (uint) { return a + b; } + } + + // This will not compile + contract D { + function readData() public { + C c = new C(); + uint local = c.f(7); // error: member `f` is not visible + c.setData(3); + local = c.getData(); + local = c.compute(3, 5); // error: member `compute` is not visible + } + } + + contract E is C { + function g() public { + C c = new C(); + uint val = compute(3, 5); // access to internal member (from derived to parent contract) + } + } + +.. index:: ! getter;function, ! function;getter +.. _getter-functions: + +Getter Functions +================ + +The compiler automatically creates getter functions for +all **public** state variables. For the contract given below, the compiler will +generate a function called ``data`` that does not take any +arguments and returns a ``uint``, the value of the state +variable ``data``. State variables can be initialized +when they are declared. + +:: + + pragma solidity >=0.4.0 <0.6.0; + + contract C { + uint public data = 42; + } + + contract Caller { + C c = new C(); + function f() public view returns (uint) { + return c.data(); + } + } + +The getter functions have external visibility. If the +symbol is accessed internally (i.e. without ``this.``), +it evaluates to a state variable. If it is accessed externally +(i.e. with ``this.``), it evaluates to a function. + +:: + + pragma solidity >=0.4.0 <0.6.0; + + contract C { + uint public data; + function x() public returns (uint) { + data = 3; // internal access + return this.data(); // external access + } + } + +If you have a ``public`` state variable of array type, then you can only retrieve +single elements of the array via the generated getter function. This mechanism +exists to avoid high gas costs when returning an entire array. You can use +arguments to specify which individual element to return, for example +``data(0)``. If you want to return an entire array in one call, then you need +to write a function, for example: + +:: + + pragma solidity >=0.4.0 <0.6.0; + + contract arrayExample { + // public state variable + uint[] public myArray; + + // Getter function generated by the compiler + /* + function myArray(uint i) returns (uint) { + return myArray[i]; + } + */ + + // function that returns entire array + function getArray() returns (uint[] memory) { + return myArray; + } + } + +Now you can use ``getArray()`` to retrieve the entire array, instead of +``myArray(i)``, which returns a single element per call. + +The next example is more complex: + +:: + + pragma solidity >=0.4.0 <0.6.0; + + contract Complex { + struct Data { + uint a; + bytes3 b; + mapping (uint => uint) map; + } + mapping (uint => mapping(bool => Data[])) public data; + } + +It generates a function of the following form. The mapping in the struct is omitted +because there is no good way to provide the key for the mapping: + +:: + + function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) { + a = data[arg1][arg2][arg3].a; + b = data[arg1][arg2][arg3].b; + } |