大家好,我是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​​就无能为力了。

那么针对我们的​​address​​​和​​uint160​​,是不是也是如此呢?

在前面的以太坊地址的本质内容中,我们介绍过,​​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​​​中,为我们提供了一种​​命名参数​​给函数赋值的方式,相对来说,更加灵活,当参数多的时候,优势就体现出来了。

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

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

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

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


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​​。但相对来说,还是挺工整的。下面我们看看这个执行结果。

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

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

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 生命周期

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