基于以太坊的智能合约开发Solidity(函数继承篇)

参考教程:【实战篇】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 = a+b;multiply = a*b;}//返回多个参数时return语句要加括号function test4(uint a,uint b) public view returns(uint add,uint  multiply){return (a+b,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 "I'm 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 "I'm 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 "I'm 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 "I'm 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 "I'm 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 "I'm 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方法进行外部调用}}

(2)mapping类型数据的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,以子类为准(但是不影响父类的money)uint height = 180;  //子类重写了父类的height,那么子类使用height时将以此为准(如果用public修饰该属性,那么此处生成的get方法会将父类生成的get方法覆盖,调用该方法会获取子类的height)function 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 don't 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);}}    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/210752.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发送、接收消息,界面不及时刷新

发送、接收消息后 UI 没展示,不及时刷新,大概率 是 SDK 的 UI 刷新功能被干扰,参考下面排查: 检查 initWithAppkey 和 connectWithToken 使用的是否是 IMKit 核心类 RCIM 的方法,如果不是,请换成 RCIM 的。…

【刷题】位运算

2 n 2^n 2n 1<<n判断某一位是否为1 s&1<<k将上面两个组合&#xff0c;可以得到判断一个集合中哪些内容包含&#xff0c;遍历所有情况。 100140. 关闭分部的可行集合数目 一个公司在全国有 n 个分部&#xff0c;它们之间有的有道路连接。一开始&#xff0c;…

CentOS 7 离线安装达梦数据库8.0

前期准备工作 确认操作系统的版本和数据库的版本是否一致 ## 查看系统版本&#xff1a;cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core)关闭防火墙和Selinux # 查看selinux是不是disabled / enforce cat /etc/selinux/config## 查看防火墙状态 firewall-cmd …

数据结构之归并排序及排序总结

目录 归并排序 归并排序的时间复杂度 排序的稳定性 排序总结 归并排序 归并排序大家只需要掌握其递归方法即可&#xff0c;非递归方法由于在某些特殊场景下边界难控制&#xff0c;我们一般很少使用非递归实现归并排序。那么归并排序的递归方法我们究竟是怎样实现呢&#xff…

PHP医院手术麻醉系统源码,laravel、vue2 、mysql技术开发,自主知识产权,二开快捷

医院手术麻醉系统全套源码&#xff0c;有演示&#xff0c;自主知识产权 技术架构&#xff1a;PHP、 js 、mysql、laravel、vue2 手术麻醉临床信息管理系统是数字化手段应用于手术过程中的重要组成部分&#xff0c;用数字形式获取并存储手术相关信息&#xff0c;既便捷又高效。…

每日一练2023.12.10—— 倒数第N个字符串【PTA】

题目链接&#xff1a;L1-050 倒数第N个字符串 题目要求&#xff1a; 给定一个完全由小写英文字母组成的字符串等差递增序列&#xff0c;该序列中的每个字符串的长度固定为 L&#xff0c;从 L 个 a 开始&#xff0c;以 1 为步长递增。例如当 L 为 3 时&#xff0c;序列为 { a…

Qt Creator设置IDE的字体、颜色、主题样式

Qt是一款开源的、跨平台的C开发框架&#xff0c;支持Windows、Linux、Mac系统&#xff0c;从1995发布第一版以来&#xff0c;发展迅猛&#xff0c;最开始是用于Nokia手机的Symbian(塞班)系统和应用程序开发&#xff0c;现在是用于嵌入式软件、桌面软件(比如WPS、VirtualBox)、A…

【图论笔记】克鲁斯卡尔算法(Kruskal)求最小生成树

【图论笔记】克鲁斯卡尔算法&#xff08;Kruskal&#xff09;求最小生成树 适用于 克鲁斯卡尔适合用来求边比较稀疏的图的最小生成树 简记&#xff1a; 将边按照升序排序&#xff0c;选取n-1条边&#xff0c;连通n个顶点。 添加一条边的时候&#xff0c;如何判断能不能添加…

Python实现PDF-Excel

轻松解决PDF格式转Excel&#xff08;使用python实现&#xff09; 实现思路&#xff1a; 要将PDF转换为Excel&#xff0c;可以使用以下步骤&#xff1a; 解析PDF内容&#xff1a;首先&#xff0c;需要使用Python中的第三方库&#xff08;如PyPDF2、pdfminer等&#xff09;来解…

西南科技大学C++程序设计实验十二(文件流操作)

一、实验目的 1. 熟悉文件的基本操作; 2. 在类中添加打开文件、保存文件、读取文件等处理函数; 二、实验任务 1. 分析完善程序:主函数创建一个文件对象,每次打开文件,在其尾部添加数据。如果文件不存在,则新建该文件。请将空白处需要完善的功能补充完整。 #include …

mybatis-config.xml的配置

1&#xff1a;MyBatis 的常规配置文件 mybatis-config.xml 包含了对 MyBatis 框架的全局配置&#xff0c;下面是一个常见的示例&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD…

Java代码重构技巧:提高可维护性和可扩展性

引言&#xff1a; 在软件开发过程中&#xff0c;代码重构是一项非常重要的任务。通过对代码进行重构&#xff0c;可以提高代码的可维护性和可扩展性&#xff0c;减少代码的复杂度&#xff0c;增加代码的可读性和可测试性。本文将介绍一些常用的Java代码重构技巧&#xff0c;帮助…

HTML中表格的语法及使用(详解)

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍HTML中表格的语法及详细使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以在评论区留…

Java集合框架定义以及整体结构

目录 一、Java集合框架1.1 什么是java集合框架1.2 集合与数组 二、集合框架具体内容2.1 整体框架2.2 遗留类和遗留接口1.3 集合框架设计特点 参考资料 一、Java集合框架 1.1 什么是java集合框架 Java集合框架&#xff08;Java Collections Framework&#xff09;是Java平台提…

高云GW1NSR-4C开发板上手使用

1.开发板 核心板&#xff0c;主芯片GW1NSR-LV4CQN48P&#xff0c;丝印文字“奥陶纪Octet&#xff0c;QQ群808770961”&#xff1a; 晶振&#xff1a;27MHz&#xff0c;22引脚 两个按键&#xff1a;靠近中间&#xff0c;23引脚&#xff0c;按下为低电平&#xff1b;靠近外侧&…

Flink 读写 HBase 总结

前言 总结 Flink 读写 HBase 版本 Flink 1.15.4HBase 2.0.2Hudi 0.13.0官方文档 https://nightlies.apache.org/flink/flink-docs-release-1.17/zh/docs/connectors/table/hbase/ Jar包 https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-hbase-2.2/1…

[Linux] yum安装分布式LNMP架构

1. 在一台主机安装nginx&#xff08;192.168.136.120&#xff09; 1.1 搭建nginx相关的yum源 cd /yum.repos.d mkdir bak mv *.repo bak vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgche…

基于Python+Django+mysql图书管理系统

基于PythonDjangomysql图书管理系统 一、系统介绍二、功能展示三、其它系统四、获取源码 一、系统介绍 程序开发软件&#xff1a;Pycharm 数据库&#xff1a;mysql 采用技术&#xff1a; Django(一个MVT框架&#xff0c;类似Java的SSM框架) 人生苦短&#xff0c;我用Python&a…

【rabbitMQ】rabbitMQ的下载,安装与配置

目录 1. 下载Erland 安装步骤&#xff1a; 配置环境变量&#xff1a; 校验环境变量配置是否成功 2.下载MQ 安装步骤&#xff1a; 添加可视化插件 &#xff1a; 启动&#xff1a; 拒绝访问 1. 下载Erland 因为rabbitMQ是基于Erland,所以在安装rabbitMQ之前需要安装Erla…

WPF(Windows Presentation Foundation)的 ToolBar控件

WPF&#xff08;Windows Presentation Foundation&#xff09;的 ToolBar 是一种用于创建工具栏的控件。 工具栏通常位于应用程序窗口的顶部或侧边&#xff0c;并提供了一组常用的工具按钮或命令&#xff0c;用于执行特定的操作或访问特定的功能。 ToolBar 控件是 WPF 中的一个…