Solidity-合约成员可见性

在 Solidity 中有两种函数调用:不需要 EVM 调用(或者说“消息调用”)的内部函数调用和需要 EVM 调用的外部调用。由此,对于函数和状态变量存在 4 种可见性。
对于函数来说,需要被指定为 external / public / internal 或者 private。相比于此,状态变量是没有 external 的。

external

外部函数是合约接口的一部分。这就意味着,它们可以通过交易(transaction)被其它合约调用。一个外部函数 f 是无法被内部调用的(因此,f() 是不起作用的,需要使用 this.f()).

public

公共函数也是合约接口的一部分,但是它同时也可以被合约内部所调用。对于一个公共 状态变量 而言,getter 函数将会自动生成。

internal

内部的函数和状态,只能在内部被调用和访问(即,只能在当前合约内部,或者其派生合约中),不能使用 this 访问。状态变量默认具有该层级的可见性。

private

私有函数和变量,只在被定义的合约内部访问,无法在派生合约中可见。

注意
事实上,合约中的所有内容(Everything inside) 对于区块链外的所有观察者来说都是可见的。使用类似 private 这类的可见性等级,旨在防止 其它合约 读取或者修改信息。

对于状态变量而言,可见性指示符在类型之后,对于函数而言,实在参数列表和返回参数列表之间。

1
2
3
4
5
6
7
8
// 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 可以调用 c.getData() 以获取 data 值。但是,它无法调用 f 函数。合约 E 继承自 C,因此,可以调用 compute 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 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)
}
}

参考链接

Contracts-Visibility and Getters

© 2024 YueGS