摘要:另外只能做状态变量,不能做本地局部变量。语法声明映射类型包括类型包括状态变量报错。可视度指的是,决定函数或者状态变量的可以被哪些智能合约可见和调用。状态变量可见性没有。在中,通过来抽象出状态变量自增的代码,并修饰。
Mapping
映射(Mappings):类似于哈希表。mapping 中任何一个可能的 key 都对应着一个 value,它的默认值是default-value 。底层用的不是使用链表 + 数组实现的,不需要扩容。value 引用存储在 keccak256(key) 表姐地址,在 storage 上存储,理论无限大。这也导致了,无法原生地遍历 mapping。另外 mapping 只能做状态变量,不能做本地局部变量。
语法
// 声明映射 // key 类型包括: bool, int/uint , address, string... // value 类型包括: any type mapping(address => uint) balances; // 状态变量 function() { mapping(address => uint) balances; // 报错。本地局部变量报错。 } // 成员赋值 balances[0x1] = 1; // 成员取值 balances[0x1] // 1 balances[0x2] // 默认值 0 balances[0x3] // 默认值 0可视度
可视度(Visibility): 可视度不是说别人无法用肉眼无法看到,智能合约部署在区块链上,代码任何人都可以看见。可视度指的是,决定函数或者状态变量的可以被哪些智能合约可见和调用。
public: 所有智能合约可见
external: 只能被外部合约或者外部调用者可见
internal: 外部合约不可见,当前合约内部和子类合约可见
private: 只有当前合约可见
可以用一个例子来解释,什么是外部合约、外部调用者、当前合约内部、子类合约。
有三个合约,Child 、 Parent 和 OutSide。其中 Child 继承 Parent, OutSide 和另外两个合约没有直接关系。
- 外部合约可见: `Child` 的函数可以调用 `OutSide` 的函数。 - 外部调用者可见: 在 remix 的 run 面板中 create `Child` 合约后,可以调用。 - 当前合约内部可见: `Child` 的函数可以调用 `Child` 自身的其他函数。 - 子类合约可见:`Child` 的函数可以调用 `Parent` 的函数。
Child 、 Parent 和 OutSide 都有以下四个函数:
function publicFunc() public {} function externalFunc() external {} function internalFunc() internal {} // 不可调用 function privateFunc() private {} // 不可调用 // `Child` 中的函数名都加了 `self` 前缀,和 Parent 中的函数做区分。
函数可见性:public(default) , external , internal , private。
具体示例代码如下:
pragma solidity ^0.4.14; import "./parent.sol"; import "./outside.sol"; contract Child is Parent{ // 返回一个值 function testOutside() { Outside o = new Outside(); o.publicFunc(); o.externalFunc(); // o.internalFunc(); // 报错。Child 不能调用 OutSide 的 internal 函数。 // o.privateFunc(); // 报错。Child 不能调用 OutSide 的 private 函数。 } function testParent () { publicFunc(); // externalFunc(); // 报错。Child 不能调用 Parent 的 external 函数。 internalFunc(); // privateFunc(); // 报错。Child 不能调用 Parent 的 private 函数。 } function selfPublicFunc() public {} function selfExternalFunc() external {} function selfInternalFunc() internal {} // remix 不可见。外部调用者不能调用 internal 函数。 function selfPrivateFunc() private {} // remix 不可见。外部调用者不能调用 private 函数。 }
状态变量可见性:public , internal(default) , private 没有 external。
状态变量可见度和函数可见度非常相似,只有一点需要特殊说明。当在状态变量上添加可视度时,编译器会给状态变量添加个 getter 函数,方便外部直接获取。
使用 remix 创建以下合约时,会出现一个 data 函数,点击该函数就可以获取到 data 的值。
<图>
继承(待补充...) 函数修饰器函数修饰器(Function Modifiers): 函数修饰器可以改变函数的行为。可通过 _ 来控制修饰器的执行时机。
在 Example1 中,通过 modifier 来抽象出检查条件的代码,并修饰 input2。让 input2 实现和 inputs2 一样的行为。其中 _ 可以简单的理解为,do something 代码在 modifier 之后执行。
contract Example1 { address owner; function Example() public { owner = msg.sender; } modifier onlyOwner { require(msg.sender == owner); _; } function inputs1() { require(msg.sender == owner); // do something... } function inputs2() onlyOwner {} }
例如:函数修饰器可以在执行自动执行指定语句。inputs1 和 inputs2 在行为上是等价的。
在 Example2 中,通过 modifier 来抽象出状态变量自增的代码,并修饰 input2。让 input2 实现和 inputs2 一样的行为。其中 _ 可以简单的理解为,do something(不包括 return) 代码在其之前执行。
contract Example2 { // 省略 ... uint output; modifier increase return(unit) { _; output++; } function change1() return(unit) { // do something... output++; return output; } function change2() increase { // do something... return output; } }Safe Math 和 Library(待完善...)
因为 Solidity 数字大多数是和钱有关的,所以在加减乘除的四则运算时,发生上溢或下溢是非常危险的。
contract Test { uint8 public a = 0; function set () { a -= 100; } function set2 () { unit8 c = a - 100; assert(c < a); a = c; } } ----- set() // a = 156 整型溢出
import "./SafeMath.sol"; // 引入 unit8 contract Test { uint8 public a = 0; function set () { a = SafeMath.sub(a, 100); } }
import "./SafeMath.sol"; // 引入 unit8 contract Test { using SafeMath for uint8; // 将 SafeMath 库里的方法,赋予了 uint8 类型。 uint8 public a = 0; function set () { a = a.sub(100); // a = SafeMath.sub(a, 100); } }其他
函数(function)声明:函数是合约内代码的可执行单元。
contract SimpleStorage { function simpleFn() { } }
函数返回值
返回一个或多个参数
直接赋值返回的命名参数,并返回
// 返回一个值 function oneParameter() returns(uint){ return 1; } // 返回多个返回值 function twoParameters() returns(uint, uint) { return (1,2); } // 命名参数直接赋值 function namedParameter() returns(uint foo, uint bar) { foo = 1; bar = 2; } // 获取返回值 function get() { uint one = oneParameter(); var (two1, two2) = twoParameters(); var (named1, named2) = namedParameter(); }
本文由【区块链研习社】优质内容计划支持,更多关于区块链的深度好文,请点击【区块链研习社】简书专栏:区块链研习社简书专栏
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/23995.html
摘要:和比特币协议有所不同的是,以太坊的设计十分灵活,极具适应性。超级账本区块链的商业应用超级账本超级账本是基金会下的众多项目中的一个。证书颁发机构负责签发撤 showImg(https://segmentfault.com/img/bV2ge9?w=900&h=385); 从比特币开始 一个故事告诉你比特币的原理及运作机制 这篇文章的定位会比较科普,尽量用类比的方法将比特币的基本原理讲出来...
摘要:舍去小数位在以太坊中账户有两种类型普通账户和智能合约账户。报酬是小额的以太币,想要运行智能合约的人的需要支付报酬来使合约工作。涉及到以太坊智能合约的攻击的问题。 智能合约可以简单的理解为一段可执行的程序片段,具体的代码经过 Solidity 编写之后,发布到区块链上。而以太坊的智能合约也可以理解为一个特殊的交易(包括可执行代码的),被发送出去后会被矿工打包记录在某一个区块中,当需要调用...
摘要:错误检查抛出异常。用于检查内部错误,比如上溢和下溢。由于语言完善的问题,支持状态变量之间的转换,未来可能会取消该限制。注意,只能将变量赋值给状态变量,而不是本地变量。因为我们只能在状态变量中分配内存空间。 错误检查 throw: 抛出异常。已被废弃。 revert(): 抛出异常,并回滚到调用前的状态。 require(bool): require(false) 抛出异常,并回...
摘要:以太坊协议的目的是普遍化,以使其核心特征能够以任意方式结合。称以太坊为一个生态系统再合适不过了核心协议由不同的基础设施编码和社群支持,他们共同构成了以太坊项目。 Web 3:去中心化应用平台很多人相信像以太坊这样一个公开、无需信任的区块链平台十分适合作为Web 3.0的共享后端,像Web3.0这样去中心化、安全的互联网,它的核心服务,比如DNS和数字身份是去中心化的,个体可以参与到经济...
阅读 2036·2021-10-12 10:12
阅读 752·2021-09-24 09:47
阅读 1161·2021-08-19 11:12
阅读 3415·2019-08-29 13:06
阅读 652·2019-08-26 11:43
阅读 2467·2019-08-23 17:20
阅读 1112·2019-08-23 16:52
阅读 2548·2019-08-23 14:27