这是个人solidity学习整理第二篇
地址(Address)
以太坊区块链由 _ account _ (账户)组成,你可以把它想象成银行账户。一个帐户的余额是 以太 (在以太坊区块链上使用的币种),你可以和其他帐户之间支付和接受以太币,就像你的银行帐户可以电汇资金到其他银行帐户一样。
每个帐户都有一个“地址”,你可以把它想象成银行账号。这是账户唯一的标识符.
Mapping(映射)
我们看到了 结构体 和 数组 。 映射 是另一种在 Solidity 中存储有组织数据的方法。
mapping (address => uint) public accountBalance; 对于金融应用程序,将用户的余额保存在一个 uint类型的变量中: mapping (uint => string) userIdToName 或者可以用来通过userId 存储/查找的用户名
映射本质上是存储和查找数据所用的键-值对。在第一个例子中,键是一个 address,值是一个 uint,在第二个例子中,键是一个uint,值是一个 string。
Msg.sender
在 Solidity 中,有一些全局变量可以被所有函数调用。 其中一个就是 msg.sender,它指的是当前调用者(或智能合约)的 address。
在 Solidity 中,功能执行始终需要从外部调用者开始。 一个合约只会在区块链上什么也不做,除非有人调用其中的函数。所以 msg.sender总是存在的。
以下是使用 msg.sender来更新 mapping 的例子:
使用 msg.sender 很安全,因为它具有以太坊区块链的安全保障 —— 除非窃取与以太坊地址相关联的私钥,否则是没有办法修改其他人的数据的
require
require使得函数在执行过程中,当不满足某些条件时抛出错误,并停止执行:
require(keccak256(_name) == keccak256("Viv")); 在调用一个函数之前,用
require验证前置条件是非常有必要的
继承
有个让 Solidity 的代码易于管理的功能,就是合约 inheritance (继承):
由于 BabyDoge 是从 Doge 那里 inherits (继承)过来的。 这意味着当你编译和部署了 BabyDoge,它将可以访问
catchphrase() 和 anotherCatchphrase()和其他我们在 Doge中定义的其他公共函数。
这可以用于逻辑继承(比如表达子类的时候,Cat 是一种 Animal)。 但也可以简单地将类似的逻辑组合到不同的合约中以组织代码。
引入(Import)
在 Solidity 中,当你有多个文件并且想把一个文件导入另一个文件时,可以使用 import 语句:
import "./someothercontract.sol";
contract newContract is SomeOtherContract { } 这样当我们在合约(contract)目录下有一个名为 someothercontract.sol的文件( ./ 就是同一目录的意思),它就会被编译器导入
Storage与Memory
在 Solidity 中,有两个地方可以存储变量 —— storage 或 memory。
Storage 变量是指永久存储在区块链中的变量。 Memory 变量则是临时的,当外部函数对某合约调用完成时,内存型变量即被移除。 你可以把它想象成存储在你电脑的硬盘或是RAM中数据的关系。
大多数时候你都用不到这些关键字,默认情况下 Solidity 会自动处理它们。 状态变量(在函数之外声明的变量)默认为“存储”形式,并永久写入区块链;而在函数内部声明的变量是“内存”型的,它们函数调用结束后消失。
然而也有一些情况下,你需要手动声明存储类型,主要用于处理函数内的 _ 结构体 _ 和 _ 数组 _ 时,当你不得不使用到这些关键字的时候,Solidity 编译器也发警示提醒你的。
internal 和 external
除 public 和 private属性之外,Solidity 还使用了另外两个描述函数可见性的修饰词:internal(内部) 和 external(外部)。
internal 和 private 类似,不过, 如果某个合约继承自其父合约,这个合约即可以访问父合约中定义的“内部”函数。。
external与public 类似,只不过这些函数只能在合约之外调用 - 它们不能被合约内的其他函数调用。
声明函数 internal或 external 类型的语法,与声明 private和 public类 型相同:
function eat() internal {}
与其他合约的交互
如果我们的合约需要和区块链上的其他的合约会话,则需先定义一个 interface (接口)。
这个过程虽然看起来像在定义一个合约,但其实内里不同:
首先,我们只声明了要与之交互的函数 —— 在本例中为 getNum —— 在其中我们没有使用到任何其他的函数或状态变量。
其次,我们并没有使用大括号({ 和 })定义函数体,我们单单用分号(;)结束了函数声明。这使它看起来像一个合约框架。
编译器就是靠这些特征认出它是一个接口的。
在我们的 app 代码中使用这个接口,合约就知道其他合约的函数是怎样的,应该如何调用,以及可期待什么类型的返回值。
使用接口
我们可以在合约中这样使用:
NumberInterface numberContract =NumberInterface(NumberInterfaceAddress); 现在变量 numberContract指向另一个合约对象
function someFunction() public {
// 现在我们可以调用在那个合约中声明的 getNum函数:
uint num=numberContract.getNum(msg.sender);
通过这种方式,只要将您合约的可见性设置为public(公共)或external(外部),它们就可以与以太坊区块链上的任何其他合约进行交互。
处理多返回值
或者如果我们只想返回其中一个变量:
可以对其他字段留空:
(,,c) = multipleReturns();
if语句
if语句的语法在 Solidity 中,与在 JavaScript 中差不多:
if (keccak256(sandwich) == keccak256("BLT")) {
eat();
}