第二課是殭屍獵食,將把app變得更像一個遊戲,新增多人模式,建立更多創造殭屍的方法。
chapter1
依然是簡介
chapter2:對映和地址
對映相當於一個索引,指向不同地址,不同地址儲存的資料不同,相當於一種特殊的儲存結構。此例中用來儲存每個殭屍的上一級。
mapping(address=>uint) public accountBalance;
key是address,value是uint。
chapter3: msg.sender
指向呼叫函式的使用者地址。注意:智慧合約部署在區塊鏈上,只有當一個外部賬戶呼叫智慧合約的函式時才會執行合約,所以msg.sender總是存在的。
一個例子:
mapping (address => uint) favoriteNumber; function setMyNumber(uint _myNumber) public { // Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender` favoriteNumber[msg.sender] = _myNumber; // ^ The syntax for storing data in a mapping is just like with arrays } function whatIsMyNumber() public view returns (uint) { // Retrieve the value stored in the sender`s address // Will be `0` if the sender hasn`t called `setMyNumber` yet return favoriteNumber[msg.sender]; }
相對於其他儲存方式,運用_msg.sender更為安全,只有當你的私鑰洩露時,別人才能更改你的賬戶資料。
chapter4:require
使用require編輯限制條件,不滿足條件時程式會丟擲異常。
例子:
function sayHiToVitalik(string _name) public returns (string) { // Compares if _name equals "Vitalik". Throws an error and exits if not true. // (Side note: Solidity doesn`t have native string comparison, so we // compare their keccak256 hashes to see if the strings are equal) require(keccak256(_name) == keccak256("Vitalik")); // If it`s true, proceed with the function: return "Hi!"; }
solidity中字串不能直接比較,所以將字串進行keccak256編碼再做比較。
注:solidity比較時對兩邊順序沒有固定要求。
chapter5:繼承
類似其他面嚮物件語言的繼承,可繼承父親的public函式等。
contract Dog is Animal{}
chapter6:引入
類似其他語言的庫,易於長程式碼的模組化編輯和管理。
chapter7:storage 和 memory
storage 和 memory 是solidity中變數的兩種儲存方式,storage 永久儲存在區塊鏈上,而memory會在外部函式呼叫時清除,有點類似計算機的磁碟和ram。solidity預設函式外定義的狀態變數是storage儲存,而函式內定義的變數是memory形式儲存。
當然有時需要手動定義來滿足一些需求,不過不用擔心,solidity編譯器會在你定義不恰當的時候提出warning。
contract SandwichFactory { struct Sandwich { string name; string status; } Sandwich[] sandwiches; function eatSandwich(uint _index) public { // Sandwich mySandwich = sandwiches[_index]; // ^ Seems pretty straightforward, but solidity will give you a warning // telling you that you should explicitly declare `storage` or `memory` here. // So instead, you should declare with the `storage` keyword, like: Sandwich storage mySandwich = sandwiches[_index]; // ...in which case `mySandwich` is a pointer to `sandwiches[_index]` // in storage, and... mySandwich.status = "Eaten!"; // ...this will permanently change `sandwiches[_index]` on the blockchain. // If you just want a copy, you can use `memory`: Sandwich memory anotherSandwich = sandwiches[_index + 1]; // ...in which case `anotherSandwich` will simply be a copy of the // data in memory, and... anotherSandwich.status = "Eaten!"; // ...will just modify the temporary variable and have no effect // on `sandwiches[_index + 1]`. But you can do this: sandwiches[_index + 1] = anotherSandwich; // ...if you want to copy the changes back into blockchain storage. } }
chapter8: Zombie Dna
chapter9: 更多關於函式可見化的問題
除了public和private,solidity中還有internal和external來控制函式可見化。
internal類似於private,但有一點不同,internal定義的函式可以為外部繼承合約呼叫,而private不行。
external類似於public,但external定義的函式只能被其他合約呼叫,本合約內的函式不能呼叫。
兩者新增定義的方法相同。
chapter10:殭屍吃什麼
吃cryptoketties。估計是作者的惡作劇。實際上並不會對cryptokitties的資料產生什麼影響,只是讀取其中的資料。
所以本章的主題就是和其他的智慧合約互動。定義一個新合約,合約只含需要呼叫的合約內的函式頭部,不含其他任何函式或者變數,且用“;”代替函式體大括號。
比如有一個合約:
contract LuckyNumber { mapping(address => uint) numbers; function setNum(uint _num) public { numbers[msg.sender] = _num; } function getNum(address _myAddress) public view returns (uint) { return numbers[_myAddress]; } }
外部合約需要呼叫getNum函式,則定義介面:
contract NumberInterface { function getNum(address _myAddress) public view returns (uint); }
chapter11: 使用介面
contract MyContract { address NumberInterfaceAddress = 0xab38... // ^ The address of the FavoriteNumber contract on Ethereum NumberInterface numberContract = NumberInterface(NumberInterfaceAddress); // Now `numberContract` is pointing to the other contract function someFunction() public { // Now we can call `getNum` from that contract: uint num = numberContract.getNum(msg.sender); // ...and do something with `num` here } }
定義一個介面合約地址就好
chapter12:多引數返回值
例子:
function multipleReturns() internal returns(uint a, uint b, uint c) { return (1, 2, 3); } function processMultipleReturns() external { uint a; uint b; uint c; // This is how you do multiple assignment: (a, b, c) = multipleReturns(); } // Or if we only cared about one of the values: function getLastReturnValue() external { uint c; // We can just leave the other fields blank: (,,c) = multipleReturns(); }
後續函式呼叫多引數返回函式時,可以只返回一個或若干個值,但要把其他返回值空出來,加逗號隔開就行。
chapter13:獎勵:kitty基因
讓那些繼承自kitty的zombies有獨特的特徵,即修改定義殭屍特徵的16位數的最後兩位。
chapter14:部署合約