可見性和getter

2022-05-16 10:45 更新

狀態(tài)變量可見性

public

公共狀態(tài)變量與內(nèi)部變量的不同之處僅在于編譯器會自動為它們生成 getter 函數(shù),這允許其他合約讀取它們的值。當在同一個合約中使用時,外部訪問(例如this.x)調(diào)用 getter,而內(nèi)部訪問(例如x)直接從存儲中獲取變量值。不生成設置器函數(shù),因此其他合約無法直接修改它們的值。

internal

內(nèi)部狀態(tài)變量只能從它們在衍生合同中定義的合同中訪問。它們不能被外部訪問。這是狀態(tài)變量的默認可見性級別。

private

私有狀態(tài)變量類似于內(nèi)部變量,但它們在派生合約中不可見。

警告

制作某些東西privateinternal僅阻止其他合約讀取或修改信息,但它仍然對區(qū)塊鏈之外的整個世界可見。

功能可見性

Solidity 知道兩種函數(shù)調(diào)用:確實創(chuàng)建實際 EVM 消息調(diào)用的外部函數(shù)調(diào)用和不創(chuàng)建實際 EVM 消息調(diào)用的內(nèi)部函數(shù)調(diào)用。此外,派生合約可能無法訪問內(nèi)部功能。這產(chǎn)生了四種類型的功能可見性。

external

外部函數(shù)是合約接口的一部分,這意味著它們可以從其他合約和交易中調(diào)用。f不能在內(nèi)部調(diào)用外部函數(shù)(即f()不工作,但this.f()工作)。

public

公共函數(shù)是合約接口的一部分,可以在內(nèi)部調(diào)用,也可以通過消息調(diào)用。

internal

內(nèi)部函數(shù)只能從當前合約或從它派生的合約中訪問。它們不能被外部訪問。由于它們沒有通過合約的 ABI 暴露給外部,它們可以采用內(nèi)部類型的參數(shù),如映射或存儲引用。

private

私有函數(shù)類似于內(nèi)部函數(shù),但它們在派生合約中不可見。

警告

制作某些東西privateinternal僅阻止其他合約讀取或修改信息,但它仍然對區(qū)塊鏈之外的整個世界可見。

可見性說明符在狀態(tài)變量的類型之后以及函數(shù)的參數(shù)列表和返回參數(shù)列表之間給出。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.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;
}

在以下示例中D, 可以調(diào)用c.getData()以檢索 data狀態(tài)存儲中的值,但不能調(diào)用f。ContractE派生自 C,因此可以調(diào)用compute.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.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)
    }
}

吸氣劑函數(shù)

編譯器會自動為所有公共狀態(tài)變量創(chuàng)建 getter 函數(shù)。對于下面給出的合約,編譯器將生成一個調(diào)用的函數(shù),該函數(shù)data不接受任何參數(shù)并返回一個uint狀態(tài)變量的值data。狀態(tài)變量可以在聲明時進行初始化。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract C {
    uint public data = 42;
}

contract Caller {
    C c = new C();
    function f() public view returns (uint) {
        return c.data();
    }
}

getter 函數(shù)具有外部可見性。如果符號在內(nèi)部被訪問(即沒有this.),它的計算結果是一個狀態(tài)變量。如果它被外部訪問(即使用this.),它的計算結果是一個函數(shù)。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract C {
    uint public data;
    function x() public returns (uint) {
        data = 3; // internal access
        return this.data(); // external access
    }
}

如果您有一個public數(shù)組類型的狀態(tài)變量,那么您只能通過生成的 getter 函數(shù)檢索數(shù)組的單個元素。這種機制的存在是為了避免在返回整個陣列時產(chǎn)生高氣體成本。您可以使用參數(shù)來指定要返回的單個元素,例如 myArray(0). 如果要在一次調(diào)用中返回整個數(shù)組,則需要編寫一個函數(shù),例如:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract arrayExample {
    // public state variable
    uint[] public myArray;

    // Getter function generated by the compiler
    /*
    function myArray(uint i) public view returns (uint) {
        return myArray[i];
    }
    */

    // function that returns entire array
    function getArray() public view returns (uint[] memory) {
        return myArray;
    }
}

現(xiàn)在您可以使用getArray()來檢索整個數(shù)組,而不是 myArray(i),它每次調(diào)用都返回一個元素。

下一個例子更復雜:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract Complex {
    struct Data {
        uint a;
        bytes3 b;
        mapping (uint => uint) map;
        uint[3] c;
        uint[] d;
        bytes e;
    }
    mapping (uint => mapping(bool => Data[])) public data;
}

它生成以下形式的函數(shù)。結構中的映射和數(shù)組(字節(jié)數(shù)組除外)被省略了,因為沒有很好的方法來選擇單個結構成員或為映射提供鍵:

function data(uint arg1, bool arg2, uint arg3)
    public
    returns (uint a, bytes3 b, bytes memory e)
{
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
    e = data[arg1][arg2][arg3].e;
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號