内容简介:Solidity 0.6.x 版本中 , 继承的一些新变化。本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
Solidity 0.6.x 版本中 , 继承的一些新变化。
由登链社区翻译的Solidity 中文文档 已经通过更新到 0.6.0.
与面向对象编程类似,Solidity是一种面向合约的语言,广泛使用继承和多态,并且对于语言的发展至关重要。Solidity开发人员如果不使用这些特性很难分离逻辑及增加代码重用性。
使用Solidity 0.6版时,引入的主要改进除了引入接口继承、禁止状态变量屏蔽之外,还使现有规则更明确。 编译器继续使用C3线性化,有关继承请参见 Solidity中文文档-继承
显式使用 virtual
与 override
默认情况下,函数不再是虚函数(virtual) 。 这意味着调用非虚拟函数将始终执行该函数,而不管它的继承层次结构的其他合约。这减少了在solidity 0.5 中存在的歧义,在solidity 0.5版本中的所有函数都是隐式虚函数,从而可以在继承结构中进一步重写。 这在大型继承中尤其危险,在这种情况下,这种歧义可能导致意外的行为和错误。
例如,在下面的合约 C
中,调用 setValue
会调用最派生合约 B
的实现(因为 B 是继承关系的最后一个),但这在实现中并不明显。
pragma solidity ^0.5.17; contract A { uint public x; function setValue(uint _x) public { x = _x; } } contract B { uint public y; function setValue(uint _y) public { y = _y; } } contract C is A, B { }
而上面示例使用 0.6版编译时,编译器会报这样一个错误: Derived contract must override function "setValue". Two or more base classes define functions with the same name and parameter types
意思是:因为父合约定义具有相同名称和参数类型的函数,派生合约必须重写(override)函数“setValue”。 在上面多重继承的示例中,有同一个函数是从多个父合约(合约A和B)继承。在这种情况下,必须要重写,并且必须 override
修饰符中列出父合约。 要注意重要的一点, override(A,B)
中的顺序无关紧要, 它不会改变 super
的行为, super
仍然由继承图的C3线性化决定,即继承关系由 contract C is A, B { ... }
声明的顺序决定。
pragma solidity ^0.6.10; contract A { uint public x; function setValue(uint _x) public virtual { x = _x; } } contract B { uint public y; function setValue(uint _y) public virtual { y = _y; } } contract C is A, B { function setValue(uint _x) public override(A,B) { A.setValue(_x); } }
请注意,只有标记为 virtual
的函数才可以重写它们。 此外,任何重写的函数都必须标记为 override
。 如果重写后依旧是可重写的,则仍然需要标记为 virtual
(译者注:也就是有 override
及 vritual
两个关键字标记符)。
接口( interface
)的函数都是隐式虚函数的,因此在实现接口时,必须在实现中显式重写其函数。 这里
有关此设计的讨论。
值得注意的是,关键字 super
的工作原理与以前相同:在扁平化继承层次结构中, super
将函数调用到更上一级的函数。 外部函数( external
函数)仍然不允许使用 super
。
接口可以继承
这个是solidity 0.6新增的功能,允许接口继承接口。 派生的接口是的所有接口函数的组合。 实现合约必须实现的所有继承接口的函数。
pragma solidity ^0.6.10; interface X { function setValue(uint _x) external; } interface Y is X { function getValue() external returns (uint); } contract Z is Y { uint x; function setValue(uint _x) external override { x = _x; } function getValue() external override returns (uint) { return x; } }
请注意,如果合约未实现所有函数,则必须将合约标记为 abstract
。
pragma solidity ^0.6.10; abstract contract Z is Y { uint x; function setValue(uint _x) external override { x = _x; } }
抽象合约
在solidity 0.5版中,编译器隐式地将未实现其所有函数的合约当作是抽象合约。
pragma solidity ^0.5.17; contract X { function setValue(uint _x) public virtual; }
而在 solidity 0.6,必须显式指定,否则编译器会报错: contract X should be made abstract
意思是合约 x 应该标记为 abstract。
pragma solidity ^0.6.10; abstract contract X { function setValue(uint _x) public virtual; }
公共变量会更安全重写外部函数
尽管此功能在0.6之前就已存在,但现在更加安全,0.6会检查编译器生成getter函数与外部函数的参数和返回类型是否匹配。在0.5版本,可能允许它们有所不同,如以下示例所示:
pragma solidity ^0.5.17; interface A { function f() external pure returns(uint8); } contract B is A { uint256 public f = 257; }
在 A 接口上调用 B 会返回1 , 因为 257 转换为uint8 会溢出。
而在 solidity 0.6 会产生错误 TypeError: Overriding public state variable return types differ
(类型错误:重写的公共变量返回了不同的类型),从而强制我们解决冲突避免溢出。
pragma solidity ^0.6.10; interface A { function f() external pure returns(uint256); } contract B is A { uint256 public override f = 257; }
注意 public
的状态变量仅仅可以重写外部函数( external
)并且仍然不允许变量重写 internal
或 public
函数。
不再有状态变量遮蔽
在0.5版本编译器中允许继承具有相同名称的可见状态变量(仅在某些静态分析 工具 中提示此问题)。 下面的示例演示此设计的问题:
pragma solidity ^0.5.17; contract A { uint public x; function setValue1(uint _x) public { x = _x; } } contract B is A { uint public x; function setValue2(uint _x) public { 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: Identifier already declared
(意思是变量已经声明);
原文:https://solidity.ethereum.org/2020/06/18/solidity-0.6-inheritance/
Posted by Elena Gesheva on June 18, 2020
本翻译由登链社区及 Cell Network 赞助。
由登链社区翻译的Solidity 中文文档 已经通过更新到 0.6.0.
与面向对象编程类似,Solidity是一种面向合约的语言,广泛使用继承和多态,并且对于语言的发展至关重要。Solidity开发人员如果不使用这些特性很难分离逻辑及增加代码重用性。
使用Solidity 0.6版时,引入的主要改进除了引入接口继承、禁止状态变量屏蔽之外,还使现有规则更明确。 编译器继续使用C3线性化,有关继承请参见 Solidity中文文档-继承
显式使用 virtual
与 override
默认情况下,函数不再是虚函数(virtual) 。 这意味着调用非虚拟函数将始终执行该函数,而不管它的继承层次结构的其他合约。这减少了在solidity 0.5 中存在的歧义,在solidity 0.5版本中的所有函数都是隐式虚函数,从而可以在继承结构中进一步重写。 这在大型继承中尤其危险,在这种情况下,这种歧义可能导致意外的行为和错误。
例如,在下面的合约 C
中,调用 setValue
会调用最派生合约 B
的实现(因为 B 是继承关系的最后一个),但这在实现中并不明显。
pragma solidity ^0.5.17; contract A { uint public x; function setValue(uint _x) public { x = _x; } } contract B { uint public y; function setValue(uint _y) public { y = _y; } } contract C is A, B { }
而上面示例使用 0.6版编译时,编译器会报这样一个错误: Derived contract must override function "setValue". Two or more base classes define functions with the same name and parameter types
意思是:因为父合约定义具有相同名称和参数类型的函数,派生合约必须重写(override)函数“setValue”。 在上面多重继承的示例中,有同一个函数是从多个父合约(合约A和B)继承。在这种情况下,必须要重写,并且必须 override
修饰符中列出父合约。 要注意重要的一点, override(A,B)
中的顺序无关紧要, 它不会改变 super
的行为, super
仍然由继承图的C3线性化决定,即继承关系由 contract C is A, B { ... }
声明的顺序决定。
pragma solidity ^0.6.10; contract A { uint public x; function setValue(uint _x) public virtual { x = _x; } } contract B { uint public y; function setValue(uint _y) public virtual { y = _y; } } contract C is A, B { function setValue(uint _x) public override(A,B) { A.setValue(_x); } }
请注意,只有标记为 virtual
的函数才可以重写它们。 此外,任何重写的函数都必须标记为 override
。 如果重写后依旧是可重写的,则仍然需要标记为 virtual
(译者注:也就是有 override
及 vritual
两个关键字标记符)。
接口( interface
)的函数都是隐式虚函数的,因此在实现接口时,必须在实现中显式重写其函数。 这里
有关此设计的讨论。
值得注意的是,关键字 super
的工作原理与以前相同:在扁平化继承层次结构中, super
将函数调用到更上一级的函数。 外部函数( external
函数)仍然不允许使用 super
。
接口可以继承
这个是solidity 0.6新增的功能,允许接口继承接口。 派生的接口是的所有接口函数的组合。 实现合约必须实现的所有继承接口的函数。
pragma solidity ^0.6.10; interface X { function setValue(uint _x) external; } interface Y is X { function getValue() external returns (uint); } contract Z is Y { uint x; function setValue(uint _x) external override { x = _x; } function getValue() external override returns (uint) { return x; } }
请注意,如果合约未实现所有函数,则必须将合约标记为 abstract
。
pragma solidity ^0.6.10; abstract contract Z is Y { uint x; function setValue(uint _x) external override { x = _x; } }
抽象合约
在solidity 0.5版中,编译器隐式地将未实现其所有函数的合约当作是抽象合约。
pragma solidity ^0.5.17; contract X { function setValue(uint _x) public virtual; }
而在 solidity 0.6,必须显式指定,否则编译器会报错: contract X should be made abstract
意思是合约 x 应该标记为 abstract。
pragma solidity ^0.6.10; abstract contract X { function setValue(uint _x) public virtual; }
公共变量会更安全重写外部函数
尽管此功能在0.6之前就已存在,但现在更加安全,0.6会检查编译器生成getter函数与外部函数的参数和返回类型是否匹配。在0.5版本,可能允许它们有所不同,如以下示例所示:
pragma solidity ^0.5.17; interface A { function f() external pure returns(uint8); } contract B is A { uint256 public f = 257; }
在 A 接口上调用 B 会返回1 , 因为 257 转换为uint8 会溢出。
而在 solidity 0.6 会产生错误 TypeError: Overriding public state variable return types differ
(类型错误:重写的公共变量返回了不同的类型),从而强制我们解决冲突避免溢出。
pragma solidity ^0.6.10; interface A { function f() external pure returns(uint256); } contract B is A { uint256 public override f = 257; }
注意 public
的状态变量仅仅可以重写外部函数( external
)并且仍然不允许变量重写 internal
或 public
函数。
不再有状态变量遮蔽
在0.5版本编译器中允许继承具有相同名称的可见状态变量(仅在某些静态分析工具中提示此问题)。 下面的示例演示此设计的问题:
pragma solidity ^0.5.17; contract A { uint public x; function setValue1(uint _x) public { x = _x; } } contract B is A { uint public x; function setValue2(uint _x) public { 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: Identifier already declared
(意思是变量已经声明);
原文: https://solidity.ethereum.org/2020/06/18/solidity-0.6-inheritance/
Posted by Elena Gesheva on June 18, 2020
本翻译由登链社区及 Cell Network 赞助。
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 33分钟前
- 阅读 ( 17 )
- 学分 ( 0 )
- 分类:Solidity
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 028.Python面向对象继承(单继承,多继承,super,菱形继承)
- PHP类继承、接口继承关系概述
- 面向对象:理解 Python 类的单继承与多继承
- java入门第二季--继承--java中的继承初始化顺序
- 前端基本功(七):javascript中的继承(原型、原型链、继承的实现方式)
- 组合还是继承,这是一个问题?——由模式谈面向对象的原则之多用组合、少用继承
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to the Design and Analysis of Algorithms
Anany Levitin / Addison Wesley / 2006-2-24 / USD 122.00
Based on a Based on a new classification of algorithm design techniques and a clear delineation of analysis methods, "Introduction to the Design and Analysis of Algorithms" presents the subject in a c......一起来看看 《Introduction to the Design and Analysis of Algorithms》 这本书的介绍吧!