0%

solidaty中函数的可见性和修饰符


前言:Solidity 语言是一种专门用于编写和执行智能合约的语言:

它是在以太坊虚拟机基础上运行的、面向合约的高级语言,最初是在 2014 年 8 月由以太坊的前任 CTO和联合创始人 Gavin Wood 提出来的,后来由以太坊开发人员组建了一支专门的团队,对 Solidity 语言进行不断改进,目前仍在开发和优化之中…..

函数:

函数是以太坊实现各种逻辑的基础,在solidaty中,函数的语法定义如下:

1
2
function + 函数的名字+(传递给函数的参数,包括参数的名称和类型) +函数可见性+函数修饰符 +returns (返回的类型,若有多个,以逗号分隔)

是不是类似于javascript,并且也可以看出区别就是相应的函数可见性和和函数修饰符还有的就是solidaty支持go语言般的可以返回多个值,对于函数可见性和修饰符的学习我觉得可以进一步加深对智能合约的理解

函数可见性:internal、private、external、public:用于设定函数的可见范围:

对于public和private来说,学过Java的都知道能够明白:

  • public:可以用来修饰变量和函数,所修饰的变量和函数,任何用户都能调用和访问,public 是默认值
  • private:可以用来修饰变量和函数,所修饰的变量和函数,只能在其所在的合约中调用和访问,即使是其子合约也没有权限访问
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //public修饰变量
    uint public num1;

    //private修饰变量
    uint private num2;

    //public修饰函数
    function myFirstHelloWorld01() public {}

    //private修饰函数
    function myFirstHelloWorld02() private {}

external和internal:

  • external:和public类似,但只用来修饰函数,并且被修饰的函数仅支持外部调用,不能在合约内部的其他函数调用

  • internal:和private类似,但只用来修饰函数,并且internal 函数只能被合约内部的函数调用;不过,如果某个合约继承自其父合约,这个合约即可以访问父合约中定义的“内部”函数。

注意:internal、private、external、public这4种关键字都是可见性修饰符,互不共存

通过一个例子加深可视化的理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
有一个A合约,它有一些可视化的函数:
-----------------
A
private pri()
internal inner()
public pub()
external ext()
-----------------

然后有一个B,合约它继承A合约:继承合约只能看到父合约中的被internal和public修饰的函数:
-----------------
B is A
internal inter()
public pub()
-----------------

最后有一个C合约调用A合约:那么C合约只能看到A合约中的被public和external修饰的函数:
-----------------
C
public pub()
external ext()
-----------------

函数修饰符:

view/constant、pure、payable、modifier:影响函数的行为

view(视图函数)/constant

被view修饰的函数不能修改状:态

1
2
3
4
5
6
//定义一个状态变量:
uint public num1;

//这个函数应该用view来修饰,读取了状态变量,但保证不修改状态
function addToNum1(uint x) external view returns (uint){
return num1 + x;

pure(纯函数)

被pure修饰的函数既不修改状态也不读取状态:

1
2
3
4
5
6
7
//定义一个状态变量:
uint public num1;

//这个函数应该用pure来修饰,既没有修改状态也没有读取状态
function addToNum2(uint x,uint y) external pure returns (uint){
return x + y;

下面的语句被认为是在修改状态:

  • 修改状态变量;
  • 触发事件;
  • 创建其他合约;
  • 使用 selfdestruct;
  • 通过调用发送以太币;
  • 调用任何未标记 view 或 pure 的函数;
  • 使用低级调用;
  • 使用包含某些操作码的内联汇编。

payable:

payable修饰的函数用于接受外部的支付,它们是一种可以接收以太的特殊函数;当一个函数呗payable修饰,表示调用这个函数时,可以附加发送一些ETH(也可以不发),但是没有加payable的函数,附加ETH调用会报错

modifier:

修改器(Modifiers)可以用来轻易的改变一个函数的行为。比如用于在函数执行前检查某种前置条件。修改器是一种合约属性,可被继承,同时还可被派生的合约重写(override)

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.15;

//修饰器modifier 可以轻松改变函数的行为
//比如用于在函数执行前检查某种前置条件

//具体用法:
contract modifierFun{
//1.先定义一个状态变量
uint public a;

//2.然后我们定义一个修饰器,修饰器可以接收变量
//格式:modifier 修饰器名字(接收变量类型 接收变量,接收变量类型 接收变量...){修饰器逻辑; _;}
modifier modifierfun(uint value){
require(value >= 10);//require函数
_;//修饰器当中的"_"符号代表所修饰函数中的代码。
a+=1;//上面"_"代表的函数代码执行完后会返回来执行完modifier当中的剩余代码
}

//3.定义一个被modifier修饰的函数
//如果执行这个函数,需要先执行修饰器当中的代码,然后再执行函数中的代码
function setValue(uint num) external modifierfun(num){
a = num;
}

//4.定义一个函数,返回设置的状态变量
function getValue() external view returns (uint){
return a;
}

//5.多重modifier:

uint public b = 0;

modifier mod{
b = 1;
_;
b = 5;
}

modifier mod1{
b = 3;
_;
b = 4;
}

//格式:再修饰符的位置添上n个modifier嵌套
function test() public mod mod1{
b = 100;
}
//上面是两个modifier修饰的函数,执行顺序为b=1 ---> b=3 ----> b=100 ----> b=4 ----> b=5
//分析:首先执行mod中的"b = 1"的代码,因为这是modifier多重嵌套,下一行的"_"执行的是下一层也就是例子当中mod1中的代码,
//而执行到mod1中"_"的时候,这个时候已经没有下一层的嵌套了,于是执行函数体中的代码,函数体中的代码执行完后,便像压栈似的返回执行剩余未执行的代码

//理解:执行过程类似压栈,而modifier修饰器相当于一个特殊的函数

//6.总结:修饰器其实类似于一个过滤器(通常也也是过滤器的作用,比如限制只有某些地址的账户才能调用该函数-->通常与require函数搭配)

}

参考:

https://blog.csdn.net/qq_33829547/article/details/80460013

https://blog.csdn.net/HDUCheater/article/details/113312162

https://blog.csdn.net/wyf2017/article/details/108463485

坚持原创技术分享,您的支持将鼓励我继续创作.