智能合约语言 Solidity 教程系列3 - 函数类型

缺乏、安全感 2021-09-18 14:54 455阅读 0赞

Solidity 教程系列第三篇 - Solidity 函数类型介绍。
Solidity 系列完整的文章列表请查看分类-Solidity。

写在前面

Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么

本文前半部分是参考Solidity 官方文档(当前最新版本:0.4.20)进行翻译,后半部分函数可见性( public, external, internal, privite )深度分析(仅针对专栏订阅用户)。

函数类型(Function Types)

函数也是一种类型,且属于值类型。
可以将一个函数赋值给一个函数类型的变量。还可以将一个函数作为参数进行传递。也可以在函数调用中返回一个函数。
函数类型有两类:内部(internal)和外部(external)函数

内部(internal)函数只能在当前合约内被调用(在当前的代码块内,包括内部库函数,和继承的函数中)。
外部(external)函数由地址和函数方法签名两部分组成,可作为外部函数调用的参数,或返回值。

函数类型定义如下:

  1. function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]

如果函数不需要返回,则省去returns ()
函数类型默认是internal, 因此internal可以省去。但以此相反,合约中函数本身默认是public的, 仅仅是当作类型名使用时默认是internal的。

有两个方式访问函数,一种是直接用函数名f, 一种是this.f, 前者用于内部函数,后者用于外部函数。

如果一个函数变量没有初始化,直接调用它将会产生异常。如果delete了一个函数后调用,也会发生同样的异常。

如果外部函数类型在Solidity的上下文环境以外的地方使用,他们会被视为function类型。它会编码为20字节的函数所在地址,和在它之前的4字节的函数方法签名一起作为bytes24类型。
合约中的public的函数,可以使用internal和external两种方式来调用。
internal访问形式为f, external访问形式为this.f

成员: 属性 selector

public (或 external) 函数有一个特殊的成员selector, 它对应一个ABI 函数选择器。

  1. pragma solidity ^0.4.16;
  2. contract Selector {
  3. function f() public view returns (bytes4) {
  4. return this.f.selector;
  5. }
  6. }

下面的代码显示内部(internal)函数类型的使用:

  1. pragma solidity ^0.4.16;
  2. library ArrayUtils {
  3. // internal functions can be used in internal library functions because
  4. // they will be part of the same code context
  5. function map(uint[] memory self, function (uint) pure returns (uint) f)
  6. internal
  7. pure
  8. returns (uint[] memory r)
  9. {
  10. r = new uint[](self.length);
  11. for (uint i = 0; i < self.length; i++) {
  12. r[i] = f(self[i]);
  13. }
  14. }
  15. function reduce(
  16. uint[] memory self,
  17. function (uint, uint) pure returns (uint) f
  18. )
  19. internal
  20. pure
  21. returns (uint r)
  22. {
  23. r = self[0];
  24. for (uint i = 1; i < self.length; i++) {
  25. r = f(r, self[i]);
  26. }
  27. }
  28. function range(uint length) internal pure returns (uint[] memory r) {
  29. r = new uint[](length);
  30. for (uint i = 0; i < r.length; i++) {
  31. r[i] = i;
  32. }
  33. }
  34. }
  35. contract Pyramid {
  36. using ArrayUtils for *;
  37. function pyramid(uint l) public pure returns (uint) {
  38. return ArrayUtils.range(l).map(square).reduce(sum);
  39. }
  40. function square(uint x) internal pure returns (uint) {
  41. return x * x;
  42. }
  43. function sum(uint x, uint y) internal pure returns (uint) {
  44. return x + y;
  45. }
  46. }

下面的代码显示外部(external)函数类型的使用:

  1. pragma solidity ^0.4.11;
  2. contract Oracle {
  3. struct Request {
  4. bytes data;
  5. function(bytes memory) external callback;
  6. }
  7. Request[] requests;
  8. event NewRequest(uint);
  9. function query(bytes data, function(bytes memory) external callback) public {
  10. requests.push(Request(data, callback));
  11. NewRequest(requests.length - 1);
  12. }
  13. function reply(uint requestID, bytes response) public {
  14. // Here goes the check that the reply comes from a trusted source
  15. requests[requestID].callback(response);
  16. }
  17. }
  18. contract OracleUser {
  19. Oracle constant oracle = Oracle(0x1234567); // known contract
  20. function buySomething() {
  21. oracle.query("USD", this.oracleResponse);
  22. }
  23. function oracleResponse(bytes response) public {
  24. require(msg.sender == address(oracle));
  25. // Use the data
  26. }
  27. }

函数可见性分析

  • public - 任意访问
  • private - 仅当前合约内
  • internal - 仅当前合约及所继承的合约
  • external - 仅外部访问(在内部也只能用外部访问方式访问)

public 还是 external 最佳实践

请订阅区块链技术查看。

参考视频

我们也推出了目前市面上最全的视频教程:深入详解以太坊智能合约语言Solidity
目前我们也在招募体验师,可以点击链接了解。

参考文档

Solidity官方文档-类型

☛ 深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

☛ 我的知识星球为各位解答区块链技术问题,欢迎加入讨论。

☛ 关注公众号“深入浅出区块链技术”第一时间获取区块链技术信息。

1615574407-5af2add5bd7b8_articlex

发表评论

表情:
评论列表 (有 0 条评论,455人围观)

还没有评论,来说两句吧...

相关阅读