以太坊开发学习-solidity(三)函数类型

目录

函数类型


函数类型

solidity官方文档里把函数归到数值类型

函数类型是一种表示函数的类型。可以将一个函数赋值给另一个函数类型的变量, 也可以将一个函数作为参数进行传递,还能在函数调用中返回函数类型变量。

函数类型有两类:- 内部(internal) 函数和 外部(external) 函数:

  1. 内部函数只能在当前合约内被调用(更具体来说, 在当前代码块内,包括内部库函数和继承的函数中), 因为它们不能在当前合约上下文的外部被执行。 调用一个内部函数是通过跳转到它的入口标签来实现的, 就像在当前合约的内部调用一个函数。

2.外部函数由一个地址和一个函数签名组成,可以通过外部函数调用传递或者返回

函数形式

复制代码
    function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]

看着些复杂,咱们从前往后一个一个看(方括号中的是可写可不写的关键字):

  1. function:声明函数时的固定用法,想写函数,就要以function关键字开头。

  2. <function name>:函数名。

  3. (<parameter types>):圆括号里写函数的参数,也就是要输入到函数的变量类型和名字。

  4. {internal|external|public|private}:函数可见性说明符,一共4种。没标明函数类型的,默认public。合约之外的函数,即"自由函数",始终具有隐含internal可见性。

    • public: 内部外部均可见。
    • private: 只能从本合约内部访问,继承的合约也不能用。
    • external: 只能从合约外部访问(但是可以用this.f()来调用,f是函数名)。
    • internal: 只能从合约内部访问,继承的合约可以用。

    Note 1 : 没有标明可见性类型的函数,默认为public

    Note 2 : public|private|internal 也可用于修饰状态变量。 public变量会自动生成同名的getter函数,用于查询数值。

    Note 3 : 没有标明可见性类型的状态变量,默认为internal

  5. [pure|view|payable]:决定函数权限/功能的关键字。payable(可支付的)很好理解,带着它的函数,运行的时候可以给合约转入ETHpureview的介绍见下一节。

  6. [returns ()]:函数返回的变量类型和名称。

使用内部函数类型的例子

复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

library ArrayUtils {
    // 内部函数可以在内部库函数中使用,因为它们将是同一代码上下文的一部分
    function map(uint[] memory self, function (uint) pure returns (uint) f)
        internal
        pure
        returns (uint[] memory r)
    {
        r = new uint[](self.length);
        for (uint i = 0; i < self.length; i++) {
            r[i] = f(self[i]);
        }
    }

    function reduce(
        uint[] memory self,
        function (uint, uint) pure returns (uint) f
    )
        internal
        pure
        returns (uint r)
    {
        r = self[0];
        for (uint i = 1; i < self.length; i++) {
            r = f(r, self[i]);
        }
    }

    function range(uint length) internal pure returns (uint[] memory r) {
        r = new uint[](length);
        for (uint i = 0; i < r.length; i++) {
            r[i] = i;
        }
    }
}


contract Pyramid {
    using ArrayUtils for *;

    function pyramid(uint l) public pure returns (uint) {
        return ArrayUtils.range(l).map(square).reduce(sum);
    }

    function square(uint x) internal pure returns (uint) {
        return x * x;
    }

    function sum(uint x, uint y) internal pure returns (uint) {
        return x + y;
    }
}

使用外部函数类型的例子

复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;


contract Oracle {
    struct Request {
        bytes data;
        function(uint) external callback;
    }

    Request[] private requests;
    event NewRequest(uint);

    function query(bytes memory data, function(uint) external callback) public {
        requests.push(Request(data, callback));
        emit NewRequest(requests.length - 1);
    }

    function reply(uint requestID, uint response) public {
        // 这里要检查的是调用返回是否来自可信的来源
        requests[requestID].callback(response);
    }
}


contract OracleUser {
    Oracle constant private ORACLE_CONST = Oracle(address(0x00000000219ab540356cBB839Cbe05303d7705Fa)); // 已知的合约
    uint private exchangeRate;

    function buySomething() public {
        ORACLE_CONST.query("USD", this.oracleResponse);
    }

    function oracleResponse(uint response) public {
        require(
            msg.sender == address(ORACLE_CONST),
            "Only oracle can call this."
        );
        exchangeRate = response;
    }
}

返回值 return 和 returns

Solidity有两个关键字与函数输出相关:returnreturns,他们的区别在于:

  • returns加在函数名后面,用于声明返回的变量类型及变量名;

  • return用于函数主体中,返回指定的变量。

    复制代码
      // 返回多个变量
      function returnMultiple() public pure returns(uint256, bool, uint256[3] memory){
              return(1, true, [uint256(1),2,5]);
          }

上面这段代码中,我们声明了returnMultiple()函数将有多个输出:returns(uint256, bool, uint256[3] memory),接着我们在函数主体中用return(1, true, [uint256(1),2,5])确定了返回值。

Go 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

// 返回多个变量
// 命名式返回
// 解构赋值

contract Return {
    // 返回多个变量
    function returnMultiple() public pure returns(uint256, bool, uint256[3] memory){
        return(1, true, [uint256(1),2,5]);
    }

    // 命名式返回
    function returnNamed() public pure returns(uint256 _number, bool _bool, uint256[3] memory _array){
        _number = 2;
        _bool = false; 
        _array = [uint256(3),2,1];
    }

    // 命名式返回,依然支持return
    function returnNamed2() public pure returns(uint256 _number, bool _bool, uint256[3] memory _array){
        return(1, true, [uint256(1),2,5]);
    }

    // 读取返回值,解构式赋值
    function readReturn() public pure{
        // 读取全部返回值
        uint256 _number;
        bool _bool;
        bool _bool2;
        uint256[3] memory _array;
        (_number, _bool, _array) = returnNamed();
        
        // 读取部分返回值,解构式赋值
        (, _bool2, ) = returnNamed();
    }
}
相关推荐
Amazing_Cacao43 分钟前
CFCA精品可可产区风土体系(亚洲):彻底拒绝应试背诵,将感官复核作为检验真实物理差异的唯一铁律
学习
ZDGJ60995 小时前
外盘期货与内盘期货交易时间核心区别
区块链
cd_949217216 小时前
数据使用控制的工程实现:数字合约、策略引擎与沙箱环境
区块链
caimouse7 小时前
protoc-gen-c 支持 proto3 `optional` 关键字修改记录
c语言·学习
憧憬成为java架构高手的小白7 小时前
黑马八股--中间件学习之MQ(RabbitMQ)
学习·中间件
撩得Android一次心动8 小时前
Linux编程笔记4【个人用】
linux·笔记·学习
user-猴子9 小时前
让网页“活”过来 —— 用AI打造会自主学习的动态知识图谱
人工智能·学习·知识图谱
Bczheng19 小时前
三十六.区块链网络(7)--修复net与测试例子
区块链
LedgerNinja10 小时前
WEEX API 稳定性实战:限频、重试与风控的工程化清单
运维·区块链
网络工程小王10 小时前
【HCIE-AI】10.pytorch模型迁移分析
人工智能·学习·华为·llama