函数重载
函数重载
函数重载
简单理解,一个合约中可以有多个同名的函数,但是这些函数的参数类型需要保证不同。
个人理解:
在 Solidity 的底层,调用函数其实并不是通过函数名来调用的,而是通过函数选择器,函数选择器是函数签名的哈希值的前4个字节。函数签名不同,得到的函数选择器就会不同。所以这不会引起冲突。(函数签名:函数名和函数的参数,不使用空格分隔,比如:
func(uint256,uint8)
)
举例,在合约A
范围内对函数f
进行重载:
contract A {
function f(uint value) public pure returns (uint out){
out = value;
}
function f(uint value, bool really) public pure returns(uint out){
if (really)
out = value;
}
}
重载函数也存在于外部接口中。如果两个外部可见函数仅区别于 Solidity 内的类型而不是他们的外部类型则会导致错误:
// 这段代码编辑器会报错
contract A {
function f(B value) public pure returns (B out) {
out = value;
}
function f(address value) public pure returns (address out) {
out = value;
}
}
contract B {
}
报错原因:虽然上面的函数传入的类型是合约类型,但在 Solidity 的底层,其实他们都是地址,导致函数选择器冲突无法编译
重载解析和参数匹配
通过将当前范围内的函数声明与函数调用中提供的参数相匹配,可以选择重载函数。 如果所有参数都可以隐式地转换为预期类型,则选择函数作为重载候选项。 如果一个候选都没有,解析失败。
返回参数不作为重载解析的依据。
上述情况指的是内部调用,外部调用直接通过函数选择器以和函数匹配,不会出现问题。
重构解析的关键点:
- 参数匹配:
- Solidity 会检查你在参数调用中提供的每个函数,看他们是否可以隐式转换为每个重载版本的对应参数类型
- 如果所有参数都可以隐式转换为某个重载版本的参数类型,那么这个版本就是一个重载候选
- 选择重载候选:
- 如果只有一个候选,那么就选择这个。
- 如果没有候选或有多个候选,解析就会失败,Solidity会报错。
- 返回参数不影响重载解析:
- 函数的返回类型不参与重载解析。即使两个重载函数的参数类型相同,但返回类型不同,Solidity也不会认为它们是有效的重载。
代码示例:
contract A {
function f(uint8 val) public pure returns (uint8 out) {
out = val;
}
function f(uint256 val) public pure returns (uint256 out) {
out = val;
}
}
首先在合约A
中已经存在了重载函数,内部调用函数时:
- 如果调用方式是
f(50)
,解释器会报错:- 因为
50
可以被隐式转换为uint8
,也可以被隐式转换为uint256
,两个重载候选冲突
- 因为
- 如果调用方式为
f(256)
则不会出现问题“- 因为
uint8
的最大值为255
,256
不会被隐式转换为uint8
,只有一个重载候选。
- 因为
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Q1ngying!