实体继承重写公共常量



简单代码:

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>Heritation>Function Overrideing(:

如果函数的参数和返回类型与变量的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) {}

常量变量的值在编译过程中赋值,然后存储在内存中。不幸的是,你无法更改它。

我不知道X在代码中的用途,但简单的状态变量可以很容易地重新分配,通过使用onlyOwner修饰符,您将可以独占访问该函数,因此您可以随时更改变量。

function changeValue(uint256 newValue) public onlyOwner {
X = newValue;
}

最新更新