solidity 语法 - 函数类型

函数类型也是值类型的一种,和C语言中的函数指针类似,用于指向一个函数,可以用于实现回掉等功能。

函数类型分为internalexternal, 标记有internal函数类型只能引用当前contract中的函数,标记有external函数类型可以应用定义在其他contract中的函数。

定义一个函数类型的基本格式如下:

function () {internal|external} [pure|constant|view|payable] [returns ()]

有如下几点需要注意:

  • 如果函数类型无返回值,可以将省略returns ()
  • 函数类型默认为internal类型,internal因此可以省略
  • public函数即可以被作为internal的函数类型使用,也可以作为external类型的函数使用。

两个例子:

pragma solidity ^0.4.23;

contract InternalFuncTest {
     event Error(bytes32 message);
    function caculate(uint p1, uint p2,bool flag) public returns(uint) {
        //The next line will get a compile error since this.add would be consideed as a external function 
        //caculate(p1,p2,flag? this.add : this.sub);
       return caculate(p1,p2,flag? add : sub);
    }
    
    function caculate(uint p1, uint p2, function (uint,uint) internal returns(uint) func ) returns(uint){
        return func(p1,p2);
    }
    
    function add(uint p1, uint p2) public returns(uint) {  
        uint sum = p1 + p2;
        if (sum < p1 || sum < p2){
            emit Error('overflow');
            return 0;
        }
        
        return sum;
    }

    function sub(uint p1, uint p2) public returns(uint) {  
        return p2 < p1 ? p1 -p2 : p2 - p1;
    }
}

上面的例子中,caculate(后一个)的第三个参数是一个internal的函数类型,接受两个uint的参数,并返回一个uint.

pragma solidity ^0.4.23;

contract RequetQueue {
    
    struct Request {
        uint id;
        function (uint,uint) external callback;
    }

    uint constant MAX_LENGTH = 5;
    Request[MAX_LENGTH] queue;
    uint front;
    uint rear;
    bool isEmpty;
    bool isFull;
    
    constructor() public {
          front = 0;
          rear = 0;
          isEmpty = true;
          isFull = false;
    }
    
    function size() public view returns(uint) {
        uint result;
        if (rear > front){
            result = rear - front;
        } else  if(rear > front) {
            result = rear - front + MAX_LENGTH;
        } else {
            result = isEmpty ? 0 : MAX_LENGTH;
        }
        return result;
    }

    function request(uint id, function(uint,uint) external callback) public returns(bool) {
        bool ret = !isFull;
        if (!isFull) {
            queue[rear].id = id;
            queue[rear].callback = callback;
            rear = (rear + 1) % MAX_LENGTH;
            isFull = rear == front;
            isEmpty = false;
        }
        
        return ret;
    }
    
    function process(function(uint) external returns(uint) handler) public returns(bool) {
        bool ret = !isEmpty;
        
        if (!isEmpty) {
            Request storage r = queue[front];
            front = (front + 1) % MAX_LENGTH;
            isFull = false;
            isEmpty = rear == front;
            uint result = handler(r.id);
            r.callback(r.id,result);
        }
        return ret;
    }
    
}

contract Requester {
    
    event PringResult(address msgSender, uint id, uint ret);
    
    RequetQueue queue;
    
    constructor(address externalFunctionTypeTestAddress) public {
        queue = RequetQueue(externalFunctionTypeTestAddress);
    }
    
    function request(uint id) public {
        //Write like this "test.request(id, callback);" will get a compile error cause with out this callback was considered as a internal function
        queue.request(id, this.callback);
    }

    function callback(uint id, uint ret) external {
        emit PringResult(msg.sender,id,ret);
    } 
}

contract Processer {
    
   event Handled(address msgSender, uint val);
    
    RequetQueue queue;
    
    constructor(address externalFunctionTypeTestAddress) public {
        queue = RequetQueue(externalFunctionTypeTestAddress);
    }
    
    function process() public {
        queue.process(this.handler);
    }
    
    function handler(uint val) public returns(uint) {
        emit Handled(msg.sender,val);
        return val + 1;
    }
}

上面的例子RequetQueue定义了一个循环队列,request和process方法分别接受一个external类型,包含一个uint参数,返回值为bool类型的函数。

你可能感兴趣的:(solidity 语法 - 函数类型)