通学智能合约系列(十三)--函数1

Posted 通学技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通学智能合约系列(十三)--函数1相关的知识,希望对你有一定的参考价值。

大家好,我是up通,通学技术,学通技术,欢迎大家继续跟我一起学习智能合约系列。

Solidity–实战篇

在实战篇当中,我们将重点介绍solidiy函数的特性。solidity学了这么久,我们会发现其实和java这种面向对象的语言还是很类似的,java类对应solidity合约。而合约的属性及函数正对应了我们java的成员变量及成员方法。编程玩的是逻辑,而逻辑的体现则是行为,行为的数字描述则是函数。

我们将花费巨量的篇幅来说明solidty的函数,一起加油吧。

solidity函数的标准形式我们可以概括如下:

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

1.函数的重载

在学习java的时候,也有重载的概念。正所谓当我们的一些行为模式一致时,但是当这个行为所输入的参数不一样时,便构成了重载。具体表现如下:

  • 函数的名字相同
  • 函数的参数不同(类型、数量)
  • 与函数的返回值无关

具体我们来看一下代码:

pragma solidity ^0.4.16;

contract overLoadTest{
    
    // 不带参数
    function test(){
        
    }
    
    // 带一个参数
    function test(address account){
        
        
    }
    
    // 参数类型不同--uint160可以和address直接转化 但仍然满足重载的条件 
    function test(uint160 account){
        
    }
    
    // 参数个数不同
    function test(uint160 account,address otherAccount){
        
    }
    
    // 此方法放开注释会编译报错,因为重载并不关心返回结果(不考虑函数的返回值是否相同)
    // function test(address account) returns(address sender){
    //     return msg.sender;
    // }
   
}

重载虽然优雅,但是以下这种情况要注意呐!!!

    uint public result = 0; 
    
    function negativeExample1(uint id){
        result = 100; 
    }
    
    function negativeExample1(uint8 id){
        result = 200;
    }
    
    function test1(){
        negativeExample1(1);
    }

编译上述代码后,编译器会提示我们如下错误:

browser/Math.sol:40:9: TypeError: No unique declaration found after argument-dependent lookup.
        negativeExample1(1);
        ^--------------^

意思就是说,在调用test1函数的时候,编译器检查了函数入参发现声明不唯一。因为我们的1既可以用uint接收,也可以用uint8来接收。

但是当我们调用negativeExample(256)的时候编译过程就不会报错了,这个时候只能接收最大值为255的uint8就无能为力了。

那么针对我们的addressuint160,是不是也是如此呢?

在前面的以太坊地址的本质内容中,我们介绍过,address本质上就是一个uint160的一串数字。所以显然也会发生上述同样的问题。

 function negativeExample2(address account){
        result = 100;
    }
    
    function negativeExample2(uint160 account){
        result = 200;
    }
    
    // 此处放开注释 自动编译报错
    //function test2(){
    //  negativeExample2(256);
    //}

所以在我们写合约的过程中,要注意这种情况,杜绝此类写法。

2.函数命名参数

pragma solidity ^0.4.16;

contract functionParamTest{
    
    
   uint public id;
   
   string public name;
   
   function setParam(uint _id,string _name){
       id = _id;
       name = _name;
   }
   
   function test(){
       setParam(18,"xiaofang");
   }
   
   function test2(){
       setParam({_id:18,_name:"xiaofang"});
   }
   
   function test3(){
       setParam({_name:"xiaofang",_id:18});
   }
//   编译报错   
//   function test4(){
//       setParam(18);
//   }


  
}

solidity中,为我们提供了一种命名参数给函数赋值的方式,相对来说,更加灵活,当参数多的时候,优势就体现出来了。

另外在我们写合约的时候,调用函数时参数个数必须是相同的,但是在外部调用的时候,我们可以少传参数(很不建议),如下图:

在这里插入图片描述

命名参数还是比较简单的,我们就介绍到这里。

哦,对了。差点忘了,这里讲一个开发小规范哈:

solidity 内部函数参数通常会加_

3.返回值特性

solidity, sao还是你sao。

至于怎么sao,来看下面这段代码。

pragma solidity ^0.4.16;

contract functionReturnTest{
    
  // 最常规的返回值写法  
  function test() view returns(uint){
      return 10;
  }
  // 返回值也可以进行一个命名
  function test1() view returns(uint result){
      return result;
  }
  
  // 可以返回任意匹配类型的值
  function test2() view returns(uint result){
      
      uint a = 10;
      result = 100;
      return a;
  }
  // 可以返回任意匹配类型的值2
  function test3() view returns(uint result){
      uint a = 10;
      result = 100;
      return 1;
  }
  
  // 可以返回多个参数 不用加return 必须要给返回值赋值
  function test4(uint a,uint b) view returns(uint add,uint multiply){
      add = a+b;
      multiply = a*b;
  }
  
  // 可以返回多个参数的简写
  function test5(uint a,uint b) view returns(uint add,uint  multiply){
      return (a+b,a*b);
  }
  
  // 可以直接进行一个交换操作
  function test6(uint a,uint b) view returns(uint _b, uint _a){
      return (b,a);
  }
  
  // 可以直接返回任意匹配多个参数的值
  function test7() view returns(uint a,uint b){
      return (10,6);
  }

  
}

此处,关于返回值的灵活写法,让我觉得又有点像python。但相对来说,还是挺工整的。下面我们看看这个执行结果。

在这里插入图片描述

好了 ,关于返回值的特性,也就介绍到这里,相对来说,也是比较简单的。

4.变量的生命周期与作用域

4.1 作用域

针对于有编程经验的人呢,这个内容就不用过多解释了。

针对没有编程经验的人呢,只要记住作用范围是通过{}来划分的即可。

下面的代码大家可以直接执行理解即可。

pragma solidity ^0.4.16;

contract scopeTest{
    
  uint public a = 100;
  
  uint b  = 200;
  
  //uint a = 100;
  
  function test() view returns(uint){
      uint a = 300;
      a = 700;
      return a;
  }
  
  function test2(uint a) view returns(uint){
      //uint a;
    //   for(uint a = 0; a<5;a++){
          
    //   }
    
    {
        // uint a;
        a = 700;
        return a;
    }
  }
  
}
4.2 生命周期

作用域头生、作用域尾死。

以上是关于通学智能合约系列(十三)--函数1的主要内容,如果未能解决你的问题,请参考以下文章

通学智能合约系列(十四)--函数2

通学智能合约系列(十四)--函数2

通学智能合约系列(十八)--函数的重写与自我销毁

通学智能合约系列(十七)--函数的重写与自我销毁

通学智能合约系列(十七)--函数与Getter

通学智能合约系列(十六)--函数与Getter