本节主要介绍修饰符的用法及其区别。
函数的可见性修饰符包括:internal、public、private、external
还有一些修饰符,主要对状态变量的修改能力进行规定:constant、payable、view、pure。
文章目录
1.修饰符说明
1.1 internal修饰符
internal声明的函数和状态变量只能通过内部访问,如在当前合约中调用或在继承的合约中调用。internal为默认的修饰符,如果大家有学过java或者C++的话,internal类似于其中的protected。另外,要注意的是,internal声明的函数是不能从外部访问的。
- 实操:
pragma solidity ^0.8.0;
contract MyContract {
uint public publicVariable;
uint internal internalVariable;
//constructor用于初始化类的对象。它是在创建对象时自动调用的
constructor(uint _publicVariable, uint _internalVariable) public {
publicVariable = _publicVariable;
internalVariable = _internalVariable;
}
function getInternalVariable() internal view returns (uint) {
return internalVariable;
}
}
1.2 external修饰符
外部函数是合约接口的一部分,所以可以从其他合约或通过交易来发起调用。比如,外部函数a()不能通过内部方法发起调用,那么怎么解决这个问题呢,我们可以通过this.a来调用。
- 实操
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyContract {
function myFunction() external returns (uint) {
// function code here
}
}
1.3 public修饰符
可以通过内部或者外部函数来调用,public类型的状态变量会自动创建一个访问器。
- 实操:
pragma solidity ^0.8.0;
contract MyContract {
uint public myNumber;
function setNumber(uint _number) public {
myNumber = _number;
}
}
1.4 private修饰符
私有函数和状态变量仅在当前合约中可以访问,在继承的合约中不可以访问。私有函数不是合约接口的一部分。
- 实操
pragma solidity ^0.8.0;
contract MyContract {
uint private myPrivateVariable;
function setMyPrivateVariable(uint newValue) public {
myPrivateVariable = newValue;
}
function getMyPrivateVariable() public view returns (uint) {
return myPrivateVariable;
}
}
1.5 constant修饰符
constant可以读取状态变量并返回给调用者。但是不能进行以下操作:改变事件,创建另一个合约,调用其他可能改变状态的函数。
实操:
function getNumber() public constant returns (uint) {
return 42;
}
1.6 payable 修饰符
简单来说。三个字讲清楚。转账用
- 实操:
function buySomething() public payable {
// function code here
}
1.7 view关键字
等同于constant生命的函数,只读取,不改变状态
1.8 pure 修饰符
为函数增加了很多限制,不能当问当前的状态和交易变量,不能读写状态变量
2 修饰符的区别
2.1 external和public修饰符的区别
internal和public是两个访问修饰符,用于控制函数和变量的可见性。public表示该函数或变量可以被任何人访问,而internal表示只有合约内部的函数可以访问该函数或变量。
- 实操:
public 表示函数或状态变量可以从合约内外任何地方访问
pragma solidity ^0.8.0;
contract MyContract {
uint256 public a;
function setA(uint256 _a) public {
a = _a;
}
}
在这个例子中,状态变量 a 和函数 setA 都使用了 public 关键字。这意味着我们可以从合约内外的任何地方读取和修改 a 的值,并且可以调用 setA 函数来设置 a 的值。
- 实操
internal 表示函数或状态变量只能在当前合约以及继承它的合约中访问。
pragma solidity ^0.8.0;
contract MyContract {
uint256 internal y;
function getY() internal view returns (uint256) {
return y;
}
}
contract AnotherContract is MyContract {
function test() public {
uint256 value = getY();
// do something with value
}
}
2.2 internal和external修饰符
internal 和 external 都是访问控制关键字,用于控制函数的可见性。
- 实操
internal 表示函数只能在合约内部或者继承自合约的合约中被访问。
contract MyContract {
uint256 internal x;
function foo() internal view returns (uint256) {
return x;
}
}
contract AnotherContract is MyContract {
function bar() public view returns (uint256) {
return foo();
}
}
在这个例子中,foo 函数使用了 internal 关键字,意味着它只能在 MyContract 合约内部或者继承自 MyContract 的合约(例如 AnotherContract)中被调用。
- 实操
external 表示函数只能在合约外部被调用,不能在合约内部调用
contract MyContract {
function foo() external pure returns (uint256) {
return 42;
}
}
在这个例子中,foo 函数使用了 external 关键字,意味着它只能在合约外部被调用。我们可以通过调用合约的地址和函数的签名来调用它,但不能在合约内部直接调用。
3.自定义修饰符
修饰符(Modifier)是一种可重用的代码块,可以被用于修改函数的行为。通过自定义修饰符,我们可以在不改变函数逻辑的情况下,对函数进行额外的检查或操作,从而提高合约的安全性和可读性。
- 实操
自定义修饰符的语法如下:
modifier <modifier_name>(<modifier_params>) {
// 额外的检查或操作
_; // 表示将流程交还给原来的函数体
}
其中,<modifier_name> 是修饰符的名称,<modifier_params> 是修饰符的参数,可以是任何类型。在修饰符中,我们可以添加额外的检查或操作,例如:检查调用者是否满足某些条件、记录日志、修改状态变量等等。
- 实操
修饰符可以用在函数定义时,用来对函数进行修饰。以下是一个使用自定义修饰符的示例:
contract MyContract {
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function.");
_;
}
function setOwner(address newOwner) public onlyOwner {
owner = newOwner;
}
}
在这个例子中,我们定义了一个名为 onlyOwner 的修饰符,它要求调用者必须是合约的 owner 地址。当调用 setOwner 函数时,只有合约的 owner 地址才能成功调用该函数,其他地址将会被拒绝。