待字闺中开发了一门区块链方面的课程:《深入浅出ETH原理与智能合约开发》,马良老师讲授。此简书文集记录我的学习笔记。
课程共8节课。其中,前四课讲ETH原理,后四课讲智能合约。
第七课分为三部分:
- Solidity语法之多继承
- ERC20众筹实例之合约分析
- ERC20众筹实例之部署调试
这篇文章是第七课第一部分的学习笔记:Solidity语法之多继承。
在前面的课程中,分别讲解了 Solidity 语言的两个语法难点:数组和合约,这节课继续讲解另一个语法难点:多继承,并有两个代码示例辅助理解知识点。
1、多继承规则
1.1 多继承规则
多继承规则多继承经常出现在面向对象的编程语言中。但往往有二义性,影响代码的可读性、可维护性。
在多继承中,有个经典的钻石问题。如图所示,B、C都是继承自A,D同时继承自B和C,D的test方法就会遇到问题。
Solidity 智能合约为了解决这个问题,使用了C3线性化(维基链接)。D继承B和C时,根据书写的顺序,有继承的先后,如图中虚线所示,按DCBA的顺序。
1.2 实例
example_4.sol
example_4.sol代码中,super是指父类的意思。
- Run 页面,先选择 D 合约,Deploy 部署代码;
- 再点 test 接口,下方点 Debug ;
- 在第 31、48、66 行设置断点;
- 点击跳到下一个断点,执行到第 66 行;
- 点 step into 进入到内部,执行到 C 合约内部;
- 点击跳到下一个断点,执行到第 48 行;
- 点 step into 进入到内部,执行到 B 合约内部。注意,这里不是跳到A合约,而是B合约。
- 后续演示略。从B合约可以再进入A合约。
2、复杂类型
复杂类型接下来是两个非常隐蔽的语法难点。
2.1 局部变量类型
一个函数里,局部变量的常规类型是 memory,而局部变量类型如果是复杂类型,则其缺省类型是这个复杂类型的指针。就是说,如果不显式地声明它是 memory 类型的话,它就是指向复杂类型的 storage 指针。注意这里,指针是指向 storage 的,而不是 memory 。
第二句如图。
所以,在使用时,为了避免二义性,要显式地声明变量的类型。
2.2 var 类型推导
第二个易错的错误是var类型推导。
如图举例,如果把 x 推导为 8 位无符号整型,范围是0~255,在循环函数中,永远执行不完所有的循环,这会引起死循环,直到消耗完 gas 。所以,要避免这类错误。
2.3 实例
example_5.sol
example_5.sol
- 把编译器版本设置为0.4.17,高版本的有点儿问题。
- 部署
-
点击 test_Local_Var 接口,再点击下面的Debug,在调试区可以看到state_A的长度为4,如图。
点击test_Local_Var -
在第 31 行设置一个断点,执行到断点处。此时state_A的长度变为9999,如图。
执行x.a=9999后
因为长度length就是存在起始的位置上,x.a=9999改变了这个值。因为指针缺省指向整个合约实例的存储类型状态变量的起始地址(见课件文字)。这里要特别注意!数组的长度本来应该是4,现在成了9999,这会浪费很多 gas 。
- 本例的第二个接口是 var 类型推导,前文已说明,如果用第 39 行代码,会是死循环;而用第 38 行代码,则是可以的。
小结一下,本文主要讲解了 solidity 语法难点中的多继承,并有两个代码示例辅助理解。
不足之处,请批评指正。
网友评论