1
+ .. include :: glossaries.rst
1
2
.. index :: ! contract
2
3
3
4
##########
@@ -113,12 +114,12 @@ Solidity 合约类似于面向对象语言中的类。合约中有用于数据
113
114
外部函数作为合约接口的一部分,意味着我们可以从其他合约和交易中调用。
114
115
一个外部函数 ``f `` 不能从内部调用(即 ``f `` 不起作用,但 ``this.f() `` 可以)。
115
116
当收到大量数据的时候,外部函数有时候会更有效率。
116
- ``public `` :
117
+ ``public `` :
117
118
public 函数是合约接口的一部分,可以在内部或通过消息调用。对于公共状态变量,
118
119
会自动生成一个 getter 函数(见下面)。
119
- ``internal `` :
120
+ ``internal `` :
120
121
这些函数和状态变量只能是内部访问(即从当前合约内部或从它派生的合约访问),不使用 ``this `` 调用。
121
- ``private `` :
122
+ ``private `` :
122
123
private 函数和状态变量仅在当前定义它们的合约中使用,并且不能被派生合约使用。
123
124
124
125
.. note ::
@@ -255,8 +256,8 @@ getter 函数具有外部可见性。如果在内部访问 getter(即没有 ``
255
256
function owned() public { owner = msg.sender; }
256
257
address owner;
257
258
258
- // 这个合约只定义一个 |modifier| ,但并未使用: 它将会在派生合约中用到。
259
- // |modifier| 所修饰的函数体会被插入到特殊符号 _; 的位置。
259
+ // 这个合约只定义一个修饰器 ,但并未使用: 它将会在派生合约中用到。
260
+ // 修饰器所修饰的函数体会被插入到特殊符号 _; 的位置。
260
261
// 这意味着如果是 owner 调用这个函数,则函数会被执行,否则会抛出异常。
261
262
modifier onlyOwner {
262
263
require(msg.sender == owner);
@@ -689,7 +690,7 @@ The use in the JavaScript API would be as follows:
689
690
690
691
当一个合约从多个合约继承时,在区块链上只有一个合约被创建,所有基类合约的代码被复制到创建的合约中。
691
692
692
- 总的继承系统与 `Python's <https://docs.python.org/3/tutorial/classes.html#inheritance >`_ ,非常
693
+ 总的继承系统与 `Python的继承系统 <https://docs.python.org/3/tutorial/classes.html#inheritance >`_ ,非常
693
694
相似,特别是多重继承方面。
694
695
695
696
下面的例子进行了详细的说明。
@@ -703,8 +704,8 @@ The use in the JavaScript API would be as follows:
703
704
address owner;
704
705
}
705
706
706
- // 使用 `is` 从另一个合约派生。派生合约可以访问所有非私有成员,包括内部函数和状态变量,
707
- // 但无法通过 ` this` 来外部访问。
707
+ // 使用 is 从另一个合约派生。派生合约可以访问所有非私有成员,包括内部函数和状态变量,
708
+ // 但无法通过 this 来外部访问。
708
709
contract mortal is owned {
709
710
function kill() {
710
711
if (msg.sender == owner) selfdestruct(owner);
@@ -723,8 +724,8 @@ The use in the JavaScript API would be as follows:
723
724
function unregister() public;
724
725
}
725
726
726
- // 可以多重继承。请注意,` owned` 也是 ` mortal` 的基类,
727
- // 但只有一个 ` owned` 实例(就像 C++ 中的虚拟继承)。
727
+ // 可以多重继承。请注意,owned 也是 mortal 的基类,
728
+ // 但只有一个 owned 实例(就像 C++ 中的虚拟继承)。
728
729
contract named is owned, mortal {
729
730
function named(bytes32 name) {
730
731
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
@@ -746,7 +747,7 @@ The use in the JavaScript API would be as follows:
746
747
747
748
// 如果构造函数接受参数,
748
749
// 则需要在声明(合约的构造函数)时提供,
749
- // 或在派生合约的构造函数位置以 |modifier| 调用风格提供 (见下文)。
750
+ // 或在派生合约的构造函数位置以修饰器调用风格提供 (见下文)。
750
751
contract PriceFeed is owned, mortal, named("GoldFeed") {
751
752
function updateInfo(uint newInfo) public {
752
753
if (msg.sender == owner) info = newInfo;
@@ -865,8 +866,8 @@ Solidity 借鉴了 Python 的方式并且使用“ `C3 线性化 <https://en.wik
865
866
contract A is X {}
866
867
contract C is A, X {}
867
868
868
- 代码编译出错的原因是 ``C `` 要求 ``X `` 重写 ``A``(因为定义的顺序是 ``A, X ``),
869
- 但是 ``A `` 本身要求重写``X``,无法解决这种冲突。
869
+ 代码编译出错的原因是 ``C `` 要求 ``X `` 重写 ``A `` (因为定义的顺序是 ``A, X `` ),
870
+ 但是 ``A `` 本身要求重写 ``X ``,无法解决这种冲突。
870
871
871
872
可以通过一个简单的规则来记忆:
872
873
以从“最接近的基类”(most base-like)到“最远的继承”(most derived)的顺序来指定所有的基类。
@@ -971,7 +972,7 @@ Solidity 借鉴了 Python 的方式并且使用“ `C3 线性化 <https://en.wik
971
972
struct Data { mapping(uint => bool) flags; }
972
973
973
974
// 注意第一个参数是“storage reference”类型,因此在调用中参数传递的只是它的存储地址而不是内容。
974
- // 这是库函数的一个特性。如果该函数可以被视为对象的方法,则习惯称第一个参数为 `self`。
975
+ // 这是库函数的一个特性。如果该函数可以被视为对象的方法,则习惯称第一个参数为 `self` 。
975
976
function insert(Data storage self, uint value)
976
977
public
977
978
returns (bool)
@@ -1077,17 +1078,6 @@ Solidity 借鉴了 Python 的方式并且使用“ `C3 线性化 <https://en.wik
1077
1078
}
1078
1079
}
1079
1080
1080
- As the compiler cannot know where the library will be
1081
- deployed at, these addresses have to be filled into the
1082
- final bytecode by a linker
1083
- (see :ref: `commandline-compiler ` for how to use the
1084
- commandline compiler for linking). If the addresses are not
1085
- given as arguments to the compiler, the compiled hex code
1086
- will contain placeholders of the form ``__Set______ `` (where
1087
- ``Set `` is the name of the library). The address can be filled
1088
- manually by replacing all those 40 symbols by the hex
1089
- encoding of the address of the library contract.
1090
-
1091
1081
由于编译器无法知道库的部署位置,我们需要通过链接器将这些地址填入最终的字节码中
1092
1082
(请参阅 :ref: `commandline-compiler ` 以了解如何使用命令行编译器来链接字节码)。
1093
1083
如果这些地址没有作为参数传递给编译器,编译后的十六进制代码将包含 ``__Set______ `` 形式的占位符(其中 ``Set `` 是库的名称)。
@@ -1104,27 +1094,6 @@ encoding of the address of the library contract.
1104
1094
库的调用保护
1105
1095
=============================
1106
1096
1107
- As mentioned in the introduction, if a library's code is executed
1108
- using a ``CALL `` instead of a ``DELEGATECALL `` or ``CALLCODE ``,
1109
- it will revert unless a ``view `` or ``pure `` function is called.
1110
-
1111
- The EVM does not provide a direct way for a contract to detect
1112
- whether it was called using ``CALL `` or not, but a contract
1113
- can use the ``ADDRESS `` opcode to find out "where" it is
1114
- currently running. The generated code compares this address
1115
- to the address used at construction time to determine the mode
1116
- of calling.
1117
-
1118
- More specifically, the runtime code of a library always starts
1119
- with a push instruction, which is a zero of 20 bytes at
1120
- compilation time. When the deploy code runs, this constant
1121
- is replaced in memory by the current address and this
1122
- modified code is stored in the contract. At runtime,
1123
- this causes the deploy time address to be the first
1124
- constant to be pushed onto the stack and the dispatcher
1125
- code compares the current address against this constant
1126
- for any non-view and non-pure function.
1127
-
1128
1097
如果库的代码是通过 ``CALL `` 来执行,而不是 ``DELEGATECALL `` 或者 ``CALLCODE `` 那么执行的结果会被回退,
1129
1098
除非是对 ``view `` 或者 ``pure `` 函数的调用。
1130
1099
@@ -1200,6 +1169,8 @@ Using For
1200
1169
// corresponding member functions.
1201
1170
// The following function call is identical to
1202
1171
// `Set.insert(knownValues, value)`
1172
+ // 这里, Set.Data 类型的所有变量都有与之相对应的成员函数。
1173
+ // 下面的函数调用和 `Set.insert(knownValues, value)` 的效果完全相同。
1203
1174
require(knownValues.insert(value));
1204
1175
}
1205
1176
}
@@ -1239,4 +1210,4 @@ Using For
1239
1210
}
1240
1211
1241
1212
注意,所有库调用都是实际的 EVM 函数调用。这意味着如果传递内存或值类型,都将产生一个副本,即使是 ``self `` 变量。
1242
- 使用存储引用变量是唯一不会发生拷贝的情况。
1213
+ 使用存储引用变量是唯一不会发生拷贝的情况。
0 commit comments