inheritance - Solidity 继承覆盖公共常量
问题描述
简单代码:
pragma solidity 0.8.4;
contract A {
uint256 public constant X = 1;
}
contract B is A {
uint256 override public constant X = 2;
}
不幸的是,编译错误:
TypeError: Cannot override public state variable.
--> contracts/mocks/StakePoolMock.sol:4:5:
|
4 | uint256 public constant X = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overriding public state variable is here:
--> contracts/mocks/StakePoolMock.sol:8:5:
|
8 | uint256 override public constant X = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
有没有办法覆盖公共常量?
解决方案
简短回答:不可以。您只能覆盖 Solidity 中的函数。
长答案:
有趣的是,由于编译器会为公共状态变量(包括常量)生成 getter 函数,您实际上可以使用它们来覆盖函数(Contracts > Inheritance > Function Overriding):
如果函数的参数和返回类型与变量的 getter 函数匹配,则公共状态变量可以覆盖外部函数
虽然公共状态变量可以覆盖外部函数,但它们本身不能被覆盖。
所以如果X
是一个函数,这将完全没问题:
contract A {
function X() external virtual returns (uint256) {
return 1;
}
}
contract B is A {
uint256 public constant override X = 2;
}
但是,您不能以相反的方式执行此操作,原因是这可能需要删除已为状态变量保留的插槽。基本合约可能包含通过变量访问该槽的代码,因此编译器允许这样做是不安全的。
然而,这种推理不适用于常量——它们不占用任何存储空间。当用变量覆盖变量或用常量覆盖常量时,这也不是问题。这似乎是一个纯粹的语法限制,所以如果你有一个强大的用例,你可以尝试提交一个功能请求。问题是 - 如果你想改变它的价值,它真的是一个常数吗,即使它只是一次?我认为在大多数语言中这是行不通的。您可能可以用一个新的常量来隐藏常量,但不能真正覆盖这个词的全部含义——即,从基类调用的函数会看到更改的值。
您的用例可能会更好地使用immutable
,这是一种“运行时常量”。与编译时常量不同,它不受编译器可以对常量执行的所有相同优化,并且不能在需要真正常量的上下文中使用(例如,您不能使用它来定义静态数组的长度),但它无法在运行时更改并且不占用任何存储空间,因此它可能仍符合您的要求。它只能在构造时分配一次,然后将结果硬编码在构造函数生成的字节码中。
contract A {
uint256 public immutable X;
constructor(uint256 _x) {
X = _x;
}
}
contract B is A(2) {}
推荐阅读
- wordpress - 博客文章上的神秘斜体文字
- null - 如何在 Inno Setup 中将 null 传递给外部函数
- c# - C# Newtonsoft 中的 JSON 数组迭代
- c# - 构建 .Net 库以使资源保持独立(Winforms C#)
- javascript - 如何将超链接与 javascript 或 css 分开设置?
- git - 我可以多次变基吗?
- android - Android 7.0 上的语音识别器
- sql - Redshift SQL - 获取 Web URL 的最右侧部分
- django - get_user_model() 和从 auth 导入用户的区别
- coq - 如何找到定义值的文件?