Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Solidity 源文件结构

华胥
176 0 0
源文件中可以包含任意多个合约定义、导入指令和杂注指令。
# M7 M+ F3 Q8 A3 Y版本杂注9 J5 N9 H. p3 @! E1 K; B
为了避免未来被可能引入不兼容变更的编译器所编译,源文件可以(也应该)被所谓的版本 杂注pragma 所注解。 我们力图把这类变更做到尽可能小,特别是,我们需要以一种当修改语义时必须同步修改语法的方式引入变更,当然这有时候也难以做到。 因此,至少对含重大变更的版本,通读变更日志永远是好办法。 这些版本的版本号始终是0.x.0或者x.0.0的形式。; p. }2 o+ |7 z$ D0 b( c
版本杂注使用如下:
8 y/ o$ V3 J4 J' _pragma solidity ^0.4.0;# Y$ W  W8 L3 _9 F. R7 ^7 W9 o
这样,源文件将既不允许低于 0.4.0 版本的编译器编译, 也不允许高于(包含) 0.5.0 版本的编译器编译(第二个条件因使用 ^ 被添加)。 这种做法的考虑是,编译器在 0.5.0 版本之前不会有重大变更,所以可确保源代码始终按预期被编译。 上面例子中不固定编译器的具体版本号,因此编译器的补丁版也可以使用。
1 Z0 G0 f$ P, i9 l可以使用更复杂的规则来指定编译器的版本,表达式遵循 npm 版本语义。
/ D9 O# P$ X1 @注解0 J! s: Q+ `9 X* z4 z2 D
Pragma 是 pragmatic information 的简称,微软 Visual C++ 文档 中译为杂注。 Solidity 中沿用 C ,C++ 等中的编译指令概念,用于告知编译器 如何 编译。 ——译者注
' M  h$ R& T% j2 I导入其他源文件2 _. ]6 j5 v( }- v+ A
语法与语义
# {( Q$ _) {6 g; i) u/ o虽然 Solidity 不知道 “default export” 为何物, 但是 Solidity 所支持的导入语句,其语法同 JavaScript(从 ES6 起)非常类似。# Y6 a& ~0 b  {( U7 ~
ES6 即 ECMAScript 6.0,ES6是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布。 ——译者注+ V% y+ o5 P" q; Y5 c" s* J8 n0 |
在全局层面上,可使用如下格式的导入语句:
9 {5 f" T. l8 t% w4 N& Iimport "filename";
6 s8 Z% {) J& R1 I) v6 z( ?" U此语句将从 “filename” 中导入所有的全局符号到当前全局作用域中(不同于 ES6,Solidity 是向后兼容的)。
1 Q8 ?' q% m- l$ S0 O4 f. }import * as symbolName from "filename";- y$ [5 V* S8 P7 L  n) h
…创建一个新的全局符号 symbolName,其成员均来自 “filename” 中全局符号。" I9 ~2 P1 k# |/ T+ {- n
import {symbol1 as alias, symbol2} from "filename";% F7 ]. c& R, a# [6 z
…创建新的全局符号 alias 和symbol2,分别从 "filename" 引用 symbol1 和 symbol2 。
$ j( t9 l' y: _& W另一种语法不属于 ES6,但或许更简便:
! r' r3 {$ Z1 O& e4 z3 G7 \import "filename" as symbolName;
9 n6 [7 a9 L+ f" p8 Z这条语句等同于 import * as symbolName from "filename";。
6 i: x( c6 d: v) a路径8 ~& y/ a9 E/ e  x' o
上文中的 filename 总是会按路径来处理,以/作为目录分割符、以.标示当前目录、以..表示父目录。 当.或..后面跟随的字符是 /时,它们才能被当做当前目录或父目录。 只有路径以当前目录 . 或父目录..开头时,才能被视为相对路径。
6 i; V0 O- ]3 _% M. }用 import "./x" as x; 语句导入当前源文件同目录下的文件x。 如果用import "x" as x;代替,可能会引入不同的文件(在全局 include directory 中)。' W6 B) q8 R6 w" f
最终导入哪个文件取决于编译器(见下文)到底是怎样解析路径的。 通常,目录层次不必严格映射到本地文件系统, 它也可以映射到能通过诸如 ipfs,http 或者 git 发现的资源。4 `+ ]4 l  ^. c9 _0 T* g. W6 u( B# W8 ~
在实际的编译器中使用5 X, b/ f4 v% g% h  h" V2 e/ K
当运行编译器时,它不仅能指定如何发现路径的第一个元素,还可指定路径前缀 重映射remapping。 例如,github.com/ethereum/dapp-bin/library 会被重映射到 /usr/local/dapp-bin/library , 此时编译器将从重映射位置读取文件。如果重映射到多个路径,优先尝试重映射路径最长的一个。 这允许将比如 “” 被映射到 "/usr/local/include/solidity" 来进行“回退重映射”。 同时,这些重映射可取决于上下文,允许你配置要导入的包,比如同一个库的不同版本。" e' x0 @& a6 S- e+ D, w+ H3 V' d  f
solc:
4 Y% n  ~+ s' h/ a( c4 E8 {对于 solc(命令行编译器),这些重映射以 context:prefix=target 形式的参数提供。 其中,context: 和 =target 部分是可选的(此时 target 默认为 prefix )。 所有重映射的值都是被编译过的常规文件(包括他们的依赖),这个机制完全是向后兼容的(只要文件名不包含 = 或 : ), 因此这不是一个破坏性修改。 在 content 目录或其子目录中的源码文件中,所有导入语句里以 prefix 开头的导入文件都将被用 target 替换prefix来重定向。
* @9 K2 e2 N' b7 l举个例子,如果你已克隆github.com/ethereum/dapp-bin/ 到本地 /usr/local/dapp-bin , 可在源文件中使用:. {! I% }7 u9 N
import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;
. Z5 w" `5 W3 k# }- x% {然后运行编译器:
3 Y% F9 D( R% P" o2 y, ?6 @3 Msolc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol. C/ G2 |; h7 t0 O( F6 e
举个更复杂的例子,假设你依赖了一些使用了非常旧版本的 dapp-bin 的模块。 旧版本的 dapp-bin 已经被 checkout 到/usr/local/dapp-bin_old,此时你可使用:
# w( t# l2 y+ `+ M9 _solc module1:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ \
! o3 K6 A6 I5 g: k3 y) dmodule2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \
2 U) D  a8 g0 l0 ^( rsource.sol/ i1 n% l) \) X; q2 N, M! x
这样,module2中的所有导入都指向旧版本,而module1中的导入则获取新版本。
- |' }  G9 _: m; B3 e注意, solc 只允许包含来自特定目录的文件:它们必须位于显式地指定的源文件目录(或子目录)中,或者重映射的目标目录(或子目录)中。 如果你想直接用绝对路径来包含文件,只需添加重映射 =/。: T5 @; f1 ?  u5 W  k/ |
如果有多个重映射指向一个有效文件,那么具有最长公共前缀的重映射会被选用。7 g/ z) F0 e( I( P8 f; t
Remix:% k; M6 [. L  k+ I) g
Remix 提供一个为 github 源代码平台的自动重映射,它将通过网络自动获取文件: 比如,你可以使用 import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; 导入一个 map 迭代器。
' ?+ \0 U' s3 N8 o3 M- p6 P0 G未来, Remix 可能支持其他源代码平台。
4 j2 M; j& `& x! z8 U注释
1 _, p0 a5 F; d# a可以使用单行注释(//)和多行注释(/*...*/)
6 Q; U6 W; S# Z% v5 w2 F// 这是一个单行注释。
6 m  F" V) B/ u4 V/*" f/ {4 [$ m8 j: \' x" z& E
这是一个8 u4 t6 K$ _3 j2 V+ X  ~. f
多行注释。
: m( r. l1 N0 [0 N( K*/0 [) H3 e/ o) P5 \9 B
此外,有另一种注释称为 natspec 注释,其文档还尚未编写。 它们是用三个反斜杠(///)或双星号开头的块(/** … */)书写,它们应该直接在函数声明或语句上使用。 可在注释中使用 Doxygen 样式的标签来文档化函数、 标注形式校验通过的条件,和提供一个当用户试图调用一个函数时显示给用户的 确认文本。
# F2 a( m9 i* B( s在下面的例子中,我们记录了合约的标题、两个入参和两个返回值的说明:
2 N1 j1 X6 d- B+ upragma solidity ^0.4.0;, c. C! z1 ~! C0 e+ @; u- D, u1 a0 ]: e
/** @title 形状计算器。 */* u+ N: x0 }. d2 M+ D/ C
contract shapeCalculator {* K( r* R5 p$ Q1 g( d* O
    /** @dev 求矩形表明面积与周长。% b- t( {1 L, r# {* A5 i/ g3 B' t$ b
    * @param w 矩形宽度。; B2 n7 u- s0 M" T! k9 W2 H
    * @param h 矩形高度。
- W4 k2 B& p/ L: t0 b    * @return s 求得表面积。
6 m7 L' _- S& r. O    * @return p 求得周长。$ J% B0 M* W8 t+ t/ p# p
    */
  e7 _7 D% r4 u. }3 r    function rectangle(uint w, uint h) returns (uint s, uint p) {
0 z* q+ a  C' q& r  F  ~        s = w * h;
0 ^6 f0 o# y7 ]8 v        p = 2 * (w + h);
; h2 y$ A2 i5 _2 Z1 v: Z, f8 l1 g    }9 F0 m" D' `- p: d5 C# S; m
}
) D1 x3 C" o, B& E/ X8 f8 j" o3 h; d0 f' V? Copyright 2016-2017, Ethereum. Revision c51c7506.
8 k6 l* N5 G( l+ p. r5 x% v  Phttps://github.com/etherchina/solidity-doc-cn/blob/develop/layout-of-source-files.rst
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

华胥 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    13