售前客服二维码
文章均源于网络收集编辑侵删
提示:仅接受技术开发咨询!
由链社区翻译的中文文档[1]已更新为0.6.0。
与面向对象编程相似,Solidity是一种面向契约的语言,它广泛使用继承和多态,对语言的发展非常重要。如果不使用这些特性,稳健性开发人员很难分离逻辑并提高代码的可重用性。
当使用实性版本0.6时,引入的主要改进不仅引入了接口继承和禁止状态变量屏蔽,而且使现有规则更加清晰。编译器继续使用C3线性化。关于继承,请参考坚实中文文件-继承[2]
显式使用虚拟和覆盖
默认情况下,函数不再是虚拟的。这意味着调用非虚拟函数将总是执行该函数,而不管其继承层次结构的其他契约。这减少了0.5的不确定性。solidity 0.5中的所有函数都是隐式虚函数,可以在继承结构中进一步重写。这在大规模继承中尤其危险。在这种情况下,这种模糊可能会导致意想不到的行为和错误。
例如,在下面的契约c中,调用setValue将调用派生最多的契约b的实现(因为b是继承关系中的最后一个),但这在实现中并不明显。
务实的^0.5.17;
合同甲
uint public x;
函数setValue(uint _x) public {
x=_ x
}
}
合同乙
uint public y;
函数setValue(uint _y) public {
y=_y。
}
}
合同丙是甲,乙
}
虽然上面的例子是用0.6版编译的,但是编译器会报告这样一个错误,因为:派生契约必须重写函数“setvalue”。两个或多个基类定义具有相同名称和参数类型的函数
含义:因为父协定定义了一个具有相同名称和参数类型的函数,派生的协定必须覆盖(覆盖[3])函数“setValue”。在以上多重继承的例子中,同一个函数是从多个父契约(契约A和契约B)中继承的。在这种情况下,必须覆盖它,并且父合同必须列在覆盖修改量中。重要的是要注意,超驰(A,B)中的顺序是不相关的,它不会改变超级用户的行为。超级仍然是由继承图的C3线性化确定的,也就是说,继承关系是由契约C所声明的顺序来确定的是A,B {.}。
务实的^0.6.10;
合同甲
uint public x;
函数setValue(uint _x)公共虚拟{
x=_ x
}
}
合同乙
uint public y;
函数setValue(uint _y)公共虚拟{
y=_y。
}
}
合同丙是甲,乙
函数设置值(uint _x)公共覆盖(A,B) {
a . SetValue(_ x);
}
}
请注意,只有标记为虚拟的函数才能覆盖它们。此外,任何被覆盖的函数必须被标记为覆盖。如果重写后仍可重写,则仍需要将其标记为虚拟。
接口的函数都是隐式虚函数,所以当实现一个接口时,它的函数必须在实现中被显式重写。这里[4]是关于这个设计的讨论。
值得注意的是,关键字super的工作原理与以前相同:在平面继承层次中,super将一个函数调用到更高级别的函数。外部函数仍然不允许使用Super。
接口可以继承
这是solidity 0.6的一个新特性,它允许接口继承接口。派生接口是所有接口功能的组合。实现契约必须实现的所有继承接口的函数。
务实的^0.6.10;
接口X {
外部函数setValue(uint _x );
}
界面Y是X {
函数getValue()外部返回(uint);
}
合同Z是Y
uint x;
函数setValue(uint _x)外部覆盖{ x=_ x}
函数getValue()外部重写返回(uint) {返回x;}
}
请注意,如果合同没有实现所有功能,则合同必须标记为抽象的。
务实的^0.6.10;
抽象合同Z是Y
uint x;
函数setValue(uint _x)外部覆盖{ x=_ x}
}
抽象合同
在实性版本0.5中,编译器隐式地将没有实现所有功能的契约视为抽象契约。
务实的^0.5.17;
合同十
函数setValue(uint _x)公共虚拟;
}
在solidity 0.6中,它必须被明确指定,否则编译器将报告一个错误:契约X应该被抽象
这意味着合同x应该被标记为抽象的。
务实的^0.6.10;
抽象合同十
函数setValue(uint _x)公共虚拟;
}
公共变量可以更安全地覆盖外部函数
虽然这个函数在0.6之前就存在了,但是现在更安全了。0.6将检查编译器生成的getter函数是否与外部函数的参数和返回类型相匹配。在0.5版中,它们可以不同,如下例所示:
务实的^0.5.17;
接口A
{
函数f()外部纯返回(uint 8);
}
合同乙是甲
{
uint256公共f=257
}
在接口a上调用b将返回1,因为将257转换为uint8将溢出[5]。
在solidity 0.6中,将会有一个错误typeerror :重写不同的公共状态变量返回类型,这迫使我们解决冲突并避免溢出。
务实的^0.6.10;
接口A
{
函数f()外部纯返回(uint 256);
}
合同乙是甲
{
uint256公共超驰f=257
}
请注意,public的状态变量只能重写外部函数,并且仍然不允许该变量重写内部或公共函数。
不再有状态变量掩码
它允许在0.5编译器中继承具有相同名称的可见状态变量(这个问题只在一些静态分析工具中出现)。以下示例演示了此设计的问题:
务实的^0.5.17;
合同甲
uint public x;
函数setValue1(uint _x)公共{ x=_ x}
}
合同乙是甲
uint public x;
函数setValue2(uint _x)公共{ x=_ x}
}
在上面的例子中,a和b都有自己的x,所以调用B.setValue2(100)将把B.x设置为100,而调用B.setValue1(200)将把A.x设置为200。
对于“b”,它是“B.x”。因此,调用B.setValue2(100)将导致将B.x设置为100,而调用B.setValue1(200)将会将A.x设置为200。
这种用法现在在0.6版中被禁止,并且会引发编译器错误提示:DeclarationError :标识符已声明(意味着变量已声明);
该翻译由连锁社区[6]和细胞网络[7]赞助。
参考
[1]实诚中国文件: https://learnblockchain.cn/docs/solidity/
[2]稳健性中文文献——继承自: https://learnbockhain.cn/docs/solidity/contracts.html #索引-16
[3]override : https://learnblockchain.cn/docs/solidity/contracts . html # overriding
[4]这里是: https://github.com/ethereum/solidity/issues/8281
[5]溢出:[https://learnblockchain.cn/tags/整数溢出](https://learnbockhain.cn/tags/integer溢出)
[6]https://learnblockchain.cn连登社区:
[7]单元网络: https://www.cellnetwork.io/? UTM _ souce=learn blockchain
文章均源于网络收集编辑侵删
提示:仅接受技术开发咨询!