Solidity 0.6.x更新:继承

2020-07-01 11:31 栏目:经验之谈 来源:网络整理 查看()

由链社区翻译的中文文档[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

微信二维码
售前客服二维码

文章均源于网络收集编辑侵删

提示:仅接受技术开发咨询!

郑重申明:资讯文章为网络收集整理,官方公告以外的资讯内容与本站无关!
NFT开发,NFT交易所开发,DAPP开发 Keywords: NFT开发 NFT交易所开发 DAPP开发