关键字virtual和override在Solidity中可用于函数覆盖。
这些关键字的目的在于,当合约被继承后子合约覆盖函数将更为明确。如果父合约的某个函数被标记为virtual关键字,那么他的子合约可以通过override关键字来覆盖父函数。
但在使用这两个关键字的同时需要注意以下几点:
对于多重继承,必须在override关键字后指定定义相同函数的派生最基础的合约;
具有private可见性的函数是不能被virtual修饰的;
在抽象合约中,没有实现的函数(抽象函数)必须要被virtual关键字修饰。而在接口合约中,所有的函数都会被自动修饰上virtual(不需要添加virtual关键字);
virtual和override关键字示例:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Base {
function foo() virtual public {}
}
contract Middle is Base {}
contract Inherited is Middle {
function foo() public override {}
}
多重继承示例:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
/*
X
/ |
Y |
\ |
Z
这样的顺序是 is X,Y 因为X最基础,Y只是他的派生
X
/ \
Y A
| |
| B
\ /
Z
顺序是 is X,Y,A,B
*/
contract X{
// 注意父类方法标注了virtual 关键字,则子类必须要重写该方法
function foo() public pure virtual returns (string memory){
return "X";
}
function bar() public pure virtual returns (string memory){
return "X";
}
function x() public pure virtual returns (string memory){
return "X";
}
}
contract Y is X{
function foo() public pure virtual override returns (string memory){
return "Y";
}
function bar() public pure virtual override returns (string memory){
return "Y";
}
function y() public pure returns (string memory){
return "Y";
}
}
contract Z is X,Y{
// 需要标注函数重写自谁
function foo() public pure override(X,Y) returns (string memory){
return "Z";
}
function bar() public pure override(Y,X) returns (string memory){
return "Z";
}
}
参考资料
