Solidity 访问权限
智能合约的访问权限共有 4 种类型: private、internal、public 和 external,本章节主要讲述它们之间的区别及应用。
1. 访问权限
1.1 private
private 函数和状态变量仅在当前合约中可以访问,在继承的合约内不可访问。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Manager { function count() private pure returns(uint){ return 2; } function test() public pure returns(uint) { return count(); } }
合约内部函数 test() 调用 private 函数 count(),是可以访问的。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Employee { function count() private pure returns(uint){ return 2; } } contract Manager is Employee { function test() public pure returns(uint) { // error return count(); } }
继承合约 Manager 调用基类合约 Employee 的 private 函数 count(),就会出现编译错误。
1.2 internal
internal 函数和状态变量可以在当前合约或继承合约里调用。需要注意的是不能加前缀 this,前缀 this 是表示通过外部方式访问。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Manager { function count() internal pure returns(uint){ return 2; } function test() public pure returns(uint) { return count(); } }
合约内部函数 test() 调用 internal 函数 count(),是可以访问的。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Employee { function count() private pure returns(uint){ return 2; } } contract Manager is Employee { function test() public pure returns(uint) { return count(); } }
继承合约 Manager 调用基类合约 Employee 的 internal 函数 count(),也是可以访问的。
1.3 public
public 函数是合约接口的一部分,可以通过内部或者消息来进行调用。对于 public 类型的状态变量,会自动创建一个访问器。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Manager { function count() public pure returns(uint){ return 2; } function test() public pure returns(uint) { return count(); } }
合约内部函数 test() 调用 public 函数 count(),是可以访问的。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Employee { function count() public pure returns(uint){ return 2; } } contract Manager is Employee { function test() public pure returns(uint) { return count(); } }
继承合约 Manager 调用基类合约 Employee 的 public 函数 count(),也是可以访问的。
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Employee { function count() public pure returns(uint){ return 2; } } contract Manager { function test() public returns(uint) { Employee e = new Employee(); return e.count(); } }
外部合约 Manager 可以调用合约 Employee 的 public 函数 count()。
1.4 external
外部函数是合约接口的一部分,所以我们可以从其它合约或通过交易来发起调用。一个外部函数 f,不能通过内部的方式来发起调用,如f()不可以调用,但可以通过this.f()。
外部函数在接收大的数组数据时更加有效。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Employee { function count() external pure returns(uint){ return 2; } } contract Manager { function test() public returns(uint) { Employee e = new Employee(); return e.count(); } }
外部合约 Manager 可以调用合约 Employee 的 public 函数 count()。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract Manager { function count() external pure returns(uint){ return 2; } function test() public pure returns(uint) { return count(); } }
合约内部函数 test() 调用 public 函数 count(),是不可以访问的。
2. 默认状态
2.1 状态变量
状态变量在函数外部声明(类似于class的属性),并永久存储在以太坊区块链中,更具体地说存储在存储 Merkle Patricia 树中,这是形成帐户状态信息的一部分。
状态变量默认类型为 internal。internal 和 private 类型的变量不能被外部访问,而 public 变量能够被外部访问。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract HelloWorld{ uint a; uint internal b; uint private c; uint public d; }
a、b、c、d 均为状态变量。
变量类型为 public 时,会生成一个和变量名相同的带返回值的函数。
例如:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract HelloWorld{ uint public d; }
相当于:
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract HelloWorld{ uint public d; function d() constant returns(uint){ return d; } }
2.2 方法
合约中的方法默认为 public 类型。
// SPDX-License-Identifier: MIT pragma solidity ^0.7.0; contract HelloWorld{ function a() constant returns(uint){ return 123; } }
2.3 继承
子合约可以访问 public 和 internal,无法访问 private 类型。
下一章:Solidity 存储位置 memory,storage,calldata
引用类型在 Solidity 中数据有一个额外的属性:存储位置,可选项为 memory 和 storage。memory:存储在内存中,即分配、即使用,越过作用域则 ...