如何自学网站后台,北京建设官方网站,个人网站首页布局,网站建设优化公司哪家好参考教程#xff1a;【实战篇】1、函数重载_哔哩哔哩_bilibili
1、函数重载#xff1a;
pragma solidity ^0.5.17;contract overLoadTest
{//不带参数function test() public{}//带一个参数function test(address account) public{}//参数类型不同#xff0c;虽然uint160可…参考教程【实战篇】1、函数重载_哔哩哔哩_bilibili
1、函数重载
pragma solidity ^0.5.17;contract overLoadTest
{//不带参数function test() public{}//带一个参数function test(address account) public{}//参数类型不同虽然uint160可以和address直接转化但仍然满足重载的条件 function test(uint160 account) public{}//参数个数不同function test(uint160 account,address otherAccount) public{}// 此函数会编译报错因为重载不考虑函数的返回值类型是否相同// function test(address account) returns(address sender){// return msg.sender;// }uint public result 0; function negativeExample1(uint id) public{result 100; }function negativeExample1(uint8 id) public{result 200;}function test1() public{//negativeExample1(1); 该语句会报错因为传入函数的参数1既符合uint又符合uint8 solidity无法辨别调用哪一个函数}function negativeExample2(address account) public{result 100;}function negativeExample2(uint160 account) public {result 200;}function test2() public{//negativeExample2(1); 该语句会报错address本质上就是一个uint160的一串数字solidity无法辨别调用哪一个函数}
}
当一些行为模式一致但是这个行为所输入的参数不一样时便构成了重载具体表现如下
①函数的名字相同
②函数的参数不同类型、数量
③与函数的返回值无关
2、函数命名参数
pragma solidity ^0.5.17;contract functionParamTest
{uint public id;string public name;function setParam(uint _id,string memory _name) public {id _id;name _name;}function test() public{setParam(18,xiaofang); //正常地传参}function test2() public{setParam({_id:18,_name:xiaofang}); //通过形参名给函数传参}function test3() public{setParam({_name:xiaofang,_id:18}); //顺序可以与定义函数参数时不同在较多参数情况下命名参数对于代码的可读性有很好的提升} function test4() public{setParam(18); //调用函数传参时不可缺少参数否则编译会报错在外部调用函数时可以缺少参数但不建议缺少}
}
3、函数返回值的特性
pragma solidity ^0.5.17;contract functionReturnTest
{//最常规的返回值写法 function test() public view returns(uint){return 10;}//返回值也可以进行一个命名在returns后可以声明返回值的名称function test1() public view returns(uint result){result 1;return result; //如果不写这条语句也是可以的因为有声明过返回值的名称但不建议搞花里胡哨}//可以返回任意匹配类型的值类型必须匹配名称不匹配没关系function test2() public view returns(uint result){ uint a 10;result 100;return a;}//可以返回多个参数在声明了返回值名称的情况下可以不用写return语句但必须要给返回值赋值function test3(uint a,uint b) public view returns(uint add,uint multiply){add ab;multiply a*b;}//返回多个参数时return语句要加括号function test4(uint a,uint b) public view returns(uint add,uint multiply){return (ab,a*b);}//可以利用多返回值的特性直接进行数据交换操作function test5(uint a,uint b) public view returns(uint _b, uint _a){return (b,a);}}
4、变量的生命周期与作用域
1作用域在程序中有非常多的花括号变量定义在哪对花括号中那么这对花括号所包含的就是变量的作用域变量可以在其作用域内有效使用。注意函数形参的作用域是函数内部虽然它看起来不是定义在函数体内部
2生命周期从变量被分配空间到空间被收回的这一个时间段称为变量的生命周期变量的生命周期自其被定义开始至其作用域尾部结束没有进行手动销毁的话。
5、值传递与副本拷贝
pragma solidity ^0.5.17;contract transferValueTest
{uint public a 200;uint public b a; //将a的值赋给b但是a和b各自占有不同的空间function changIt() public{b 400; //改变b的值并不影响a}//i作为形式参数当调用该函数时是将所传值的副本传入的并不会改变所传引用的值也就是说对i做修改并不影响a的值function changeIt3(uint i) public returns(uint){i;return i;}function test() public {changeIt3(a);}}
6、const静态修饰
pragma solidity ^0.5.17;contract constantTest
{// 在0.4版本中,constant等同于view,在0.5以上的版本中已经废弃/*function test() public constant returns(uint){return 100;}*/
}
7、构造函数
pragma solidity ^0.5.17;contract constructorTest
{//初始化结果为0uint public a;//构造函数的名称与合约名相同在合约部署或者被创建的时候执行0.5以下版本支持该种语法/*function constructorTest(){a 100;}*///一个合约内部不能有多个构造函数/*function constructorTest(uint _a,uint _b){a _a;}*///在0.5以上版本中solidity采用了关键字constructor来定义构造函数constructor() public{a 100;}/*address public ower;function constructorTest() 在合约部署时可以借助构造函数传递一些内容到合约内例如部署合约的账户{ower msg.sender;}*/
}
8、函数修改器modifire
1基本用法
pragma solidity ^0.5.17;contract modifireTest
{address public ower;uint public num 0;constructor() public{ower msg.sender;}//定义一个函数修改器 modifier onlyOwer{require(msg.sender ower); //不符合条件时则抛出异常停止执行下面的语句并回滚//修饰函数时函数相当于被插入到_;位置然后把onlyOwer当作函数执行_;}function changeIt(uint _num) public onlyOwer{num _num; //该例中只有部署该合约的账户才有权利调用这个函数其它账户调用该函数将会报错//当然“require(msg.sender ower);”也可以直接写在该函数中这样就不需要借助modifier}}
Solidity的异常处理
①Solidity使用“状态恢复异常”来处理异常。这样的异常将撤消对当前调用及其所有子调用中的状态所做的所有更改并且向调用者返回错误。
②函数assert和require可用于判断条件并在不满足条件时抛出异常
• assert() 一般只应用于测试内部错误并检查常量
• require() 应用于确保满足有效条件或验证调用外部合约的返回值
• revert() 用于抛出异常它可以标记一个错误并将当前调用回退
2运用示例1
pragma solidity ^0.5.17;contract mappingTest
{//一个钱包地址对应一个个人身份id mapping(address uint) idMapping;//一个人的身份id地址对应一个人的姓名mapping(uint string) nameMapping;uint id 0;address public ower;//定义一个函数修改器 modifier onlyOwer{require(idMapping[msg.sender] 0); //判断调用函数的账户有没有绑定身份的记录以免同一账户注册多个身份//修饰函数时函数相当于被插入到_;位置然后把onlyOwer当作函数执行_;}function register(string memory name) public onlyOwer //该函数模拟新账户绑定身份{address account msg.sender; //调用该函数的账户为需要绑定身份和生成id号的新账户id; //这里的id号应该是随机生成总之每个调用该函数的账户都应该获得不同的id号//给账户分配一个ididMapping[account] id;//再将个人id与个人姓名进行映射绑定nameMapping[id] name; }//根据账户地址获取idfunction getIdByAddress(address account) public view returns(uint){return idMapping[account];}//根据id获取个人姓名function getNameById(uint id) public view returns(string memory){return nameMapping[id];}
3运用示例2
pragma solidity ^0.5.17;contract modifireTest
{uint level 200;uint money 0;modifier modifyLevel(uint _inputLevel) //函数修改器可以有参数这样使用起来更加灵活{require(level _inputLevel, Your level is not within the range!);//如不满足require中的条件错误类型为Your level is not within the range_;}function addMoney() modifyLevel(50) public {//require(level 50); 五十级以上才能调用该函数money 100;}function recoverCash() modifyLevel(200) public {//require(level 200); 两百级以上才能调用该函数money 200;}function getMoney() public view returns(uint) {return money;}}
4多重modifire的执行顺序
pragma solidity ^0.5.17;contract modifireTest4
{uint public a 0;modifier mod1{a 1; //执行顺序——1最先执行_;a 2; //执行顺序——5最后执行}modifier mod2{a 3; //执行顺序——2_;a 4; //执行顺序——4}function test() public mod1 mod2 //调用该函数后a的值为2{a 100; //执行顺序——3}}
9、合约的继承
1基本的继承
pragma solidity ^0.5.17;contract Father
{uint money 10000;function noSmoking() public view returns(string memory){return Im not somking;}
}contract Son is Father //继承语法contract 子类名称 is 父类名称1,父类名称2……
{function getMoney() public view returns(uint){return money; //子类继承了父类中的属性
}function test() public view returns(string memory){return noSmoking(); //子类继承了父类中的函数}
}
2连续继承
pragma solidity ^0.5.17;contract GrandFather
{uint height 170;
}contract Father is GrandFather
{uint money 10000;function getHeight() public view returns(uint){return height; //子类继承了父类中的属性}
}contract Son is Father
{function getHeight() public view returns(uint){return height; //子类继承了父类的父类中的属性}
}
3继承权限
①合约属性的继承
pragma solidity ^0.5.17;contract Father
{uint private privateMoney 2000; //加上private标识的属性或函数不会被子类继承//其余情况下可以被继承//uint privateMoney 2000;//uint public privateMoney 2000;//uint internal privateMoney 2000;//注意external不能修饰属性只修饰函数uint money 10000;function noSmoking() public view returns(string memory){return Im not somking;}}contract Son is Father
{function getMoney() public view returns(uint){return money; //正常“财产”可以被继承
}function getPrivateMoney() public view returns(uint){//return privateMoney; 父类的私房钱子类无法继承
}}
②public修饰父类函数
pragma solidity ^0.5.17;contract Father
{function noSmoking() public view returns(string memory){return Im not somking;}}contract Son is Father
{function test() public view returns(string memory){return noSmoking(); //子合约可以正常调用父类中public修饰的函数}}
③private修饰父类函数
pragma solidity ^0.5.17;contract Father
{function noSmoking() private view returns(string memory){return Im not somking;}}contract Son is Father
{function test() public view returns(string memory){//return noSmoking(); 子合约不可以调用父类中private修饰的函数}}
④internal修饰父类函数
pragma solidity ^0.5.17;contract Father
{function noSmoking() internal pure returns(string memory){return Im not somking;
}function test() public returns(string memory){return noSmoking(); //被internal修饰的函数只能在合约内部以及子合约中被调用外部无法直接调用}}contract Son is Father
{function test2() public pure returns(string memory){return noSmoking(); //子合约可以正常调用父类中internal修饰的函数当然也只能在合约内部调用外部不可见}}
⑤external修饰父类函数
pragma solidity ^0.5.17;contract Father
{function noSmoking() external pure returns(string memory){return Im not somking;}function test() public returns(string memory){//return noSmoking(); 被external修饰的函数只能在外部被调用合约内部以及子合约中无法直接调用return this.noSmoking(); //通过this可以让编译器认为这是在外部通过该合约地址调用该函数这样就不会报错}}contract Son is Father
{function test2() public view returns(string memory) //使用this的话千万不要使用pure{//return noSmoking();return this.noSmoking(); //子类也可以通过this调用父类中external修饰的函数}}contract Mother
{function test() public returns(string memory){Father f new Father(); //对于被external修饰的函数在其它非子合约中可以直接创建合约对象通过合约对象进行外部调用return f.noSmoking();}}
10、全局变量自动getter函数
1普通变量的get方法
pragma solidity ^0.5.17;contract GetterTest
{uint public num 100; //public修饰符修饰的属性默认会生成一个get方法供我们外部调用/*function num() external returns(uint) {return num;}1、变量用public修饰后这个函数就是生成的get方法函数体内部定义的变量不能用public修饰2、默认生成的get函数是external权限的不能够在合约的内部调用3、对于该例num()方法只能有一个要是自己进行重写就会覆盖默认生成的get方法*/function test() public{// num();this.num(); //可以通过this对get方法进行外部调用}}
2mapping类型数据的get方法
pragma solidity ^0.4.18; //编译器版本与前面例子所用的不同contract GetterTest
{mapping(uint string) public map;function map(uint key) external returns(string) //map的get方法需传入key值才能获取value值对于嵌套的mapping就需要传入多个key值{return map[key];}}
补充——mapping映射
pragma solidity ^0.5.17;contract mappingTest
{//个人认为这个有点像Python中的字典可以理解为mapping(key value) 字典名//一个钱包地址对应一个个人身份id mapping(address uint) idMapping;//一个人的身份id地址对应一个人的姓名mapping(uint string) nameMapping;uint id 0;function register(string memory name) public //该函数模拟新账户绑定身份{address account msg.sender; //调用该函数的账户为需要绑定身份和生成id号的新账户id; //这里的id号应该是随机生成总之每个调用该函数的账户都应该获得不同的id号//给账户分配一个ididMapping[account] id;//再将个人id与个人姓名进行映射绑定nameMapping[id] name; }//根据账户地址获取idfunction getIdByAddress(address account) public view returns(uint){return idMapping[account];}//根据id获取个人姓名function getNameById(uint id) public view returns(string memory){return nameMapping[id];
}mapping(uint mapping(uint mapping(uint string))) public map;function test() public{map[0][1][1] lalalalala; //mapping数据类型还可以嵌套相当于Python中的多维字典//map[0]mapping(uint mapping(uint string))//map[0][1]mapping(uint string)//map[0][1][1]string}}
mapping(key value) Mapping的相关语句
1“mapping(type1 type2) Mapping;”的作用是创建一个type1类型到type2类型的映射映射组的名称为“Mapping”。
2“Mapping[key] value;”的作用是
①如果Mapping组中此前没有key这个键值那么Mapping组中会添加key这个键值到value的映射。
②如果Mapping组中此前存在key这个键值那么key键值的映射修改为value。
11、继承中的重写
1属性重写
pragma solidity ^0.5.17;contract Father
{uint money 10000;uint public height 170; //父类属性用public修饰那么子类继承后会生成get方法调用该方法会获取父类的height而不是子类的}contract Son is Father
{uint money 20000; //子类重写了父类的money以子类为准但是不影响父类的moneyuint height 180; //子类重写了父类的height那么子类使用height时将以此为准如果用public修饰该属性那么此处生成的get方法会将父类生成的get方法覆盖调用该方法会获取子类的heightfunction getMoney() public view returns(uint){return money;}function getHeight() public view returns(uint){return height;
}}
2函数重写
pragma solidity ^0.5.17;contract Father
{uint public money 10000;function noSmoking() public view returns(string memory){return I dont smoke,and I do not drink;}
}contract Son is Father
{uint public money 20000;function noSmoking() public view returns(string memory) //子类重写了父类的函数父类函数将会被覆盖{return I do not smoke,but I do drink;}function test() public view returns(string memory){return noSmoking();}
}
12、多继承需要注意的情况
pragma solidity ^0.5.17;contract Father
{uint public money 10000;uint public height 180;}contract Mother
{uint public money 20000;uint public height 170;uint public weight 120;}contract Son is Father,Mother
{function test() public view returns(uint){return height; //会返回Mother中的height后继承的属性如果与前面继承的相同前继承的属性将会被覆盖}}
13、合约的销毁析构函数
pragma solidity ^0.5.17;contract DestructTest
{address ower;constructor() public{ower msg.sender;}uint public money 100;function increment() public{money 100;}function kill() public{if(msg.sender ower) //只有发布合约的账户有权利销毁合约{//手动进行自我销毁selfdestruct(msg.sender);}}
}