はじめに
前回のチャプター
チャプター2で学べること
アクセス修飾子やストレージ、継承など。
アドレス
- アカウントの識別子のこと。銀行口座番号のようなもの。
マッピング
// accountBalanceというマッピング。キーはaddress、バリュー(値)はuint
mapping (address => uint) public accountBalance;
// userIdToNameというマッピング。キーはuint、バリュー(値)string
mapping (uint => string) userIdToName;
msg.sender
- 全ての関数で利用できるグローバル変数
- 関数を呼び出したユーザー(またはスマートコントラクト)のaddressを参照できる
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
// msg.sender下に_myNumberを格納
favoriteNumber[msg.sender] = _myNumber;
}
function whatIsMyNumber() public view returns (uint) {
// 送信者のアドレスに格納されている値を受け取る
return favoriteNumber[msg.sender];
}
require
- ある条件を満たさない場合はエラーを投げて実行を止める
function sayHiToVitalik(string _name) public returns (string) {
// まず_nameとVitalikを比較、真でなければエラーで終了
require(keccak256(_name) == keccak256("Vitalik"));
// 真ならば、関数を処理する
return "Hi!";
}
継承
// 継承元
contract Doge {
function catchphrase() public returns (string) {
return "So Wow CryptoDoge";
}
}
// 継承先
contract BabyDoge is Doge {
function anotherCatchphrase() public returns (string) {
return "Such Moon BabyDoge";
}
}
import
import "./someothercontract.sol";
contract newContract is SomeOtherContract {
}
storageとmemory
storage
- Storage はブロックチェーン上に永久に格納される変数
- 状態変数の場合はデフォルトで storageに格納される
// 以下はエラーになる
Sandwich mySandwich = sandwiches[_index];
// 以下のように書く
Sandwich storage mySandwich = sandwiches[_index];
mySandwich.status = "Eaten!";
memory
- 一時的な変数で、外部関数をコントラクトに呼び出す際に消去される
- 関数内で宣言された変数はデフォルトで、memoryに格納される
Sandwich memory anotherSandwich = sandwiches[_index + 1];
anotherSandwich.status = "Eaten!";
アクセス修飾子
- 関数、変数につけることができるアクセス制限を可能にする
- 明示的に権限を設定していない場合、デフォルトでpublicとなる
private
|
呼び出し可否 |
コントラクト内部からの呼び出し |
◯ |
コントラクト内部からの呼び出し |
× |
継承先からの呼び出し |
× |
Internal
- そのコントラクトと、このコントラクトを継承したコントラクからのみ呼び出し可能
- privateとの違いは、コントラクトから継承したコントラクトにもアクセスできること
|
呼び出し可否 |
コントラクト内部からの呼び出し |
◯ |
コントラクト内部からの呼び出し |
× |
継承先からの呼び出し |
◯ |
public
- 継承したコントラクト、また外部から呼び出し可能
- publicな関数を外部から呼ぶと、引数の値を一度メモリに保存される
|
呼び出し可否 |
コントラクト内部からの呼び出し |
◯ |
コントラクト内部からの呼び出し |
◯ |
継承先からの呼び出し |
◯ |
external
- コントラクトの外からのみ呼び出し可能
- publicとの違いは、引数で渡された値をメモリに保存されない(publiよりガス代が安い)
|
呼び出し可否 |
コントラクト内部からの呼び出し |
× |
コントラクト外部からの呼び出し |
◯ |
継承先からの呼び出し |
× |
interface
- ブロックチェーン上の他人のコントラクトとやりとりを可能にする
- 関数宣言の終わりにセミコロンを使っていて、それでインターフェースだと判別する
// 他人のコントラクト
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];
}
}
// インターフェースの定義
contract NumberInterface {
function getNum(address _myAddress) public view returns (uint);
}
// 自分のコントラクト
contract MyContract {
address NumberInterfaceAddress = 0xab38...;
NumberInterface numberContract = NumberInterface(NumberInterfaceAddress);
function someFunction() public {
// コントラクトからgetNumを呼び出す
uint num = numberContract.getNum(msg.sender);
}
}
複数の戻り値を返却する
- solidityでは複数の戻り値を返すことができる。また、一つの値だけを取得することも可能
function multipleReturns() internal returns(uint a, uint b, uint c) {
return (1, 2, 3);
}
function processMultipleReturns() external {
uint a;
uint b;
uint c;
(a, b, c) = multipleReturns();
}
// 一つの値を取得する場合は、以下のように取得する
function getLastReturnValue() external {
uint c;
// 他のフィールドは空欄でも構わないぞ:
(,,c) = multipleReturns();
}
チャプター2のまとめ
アクセス修飾子の範囲などについての明確な違いまで理解できた。
実際の実装ではガス代の考慮まで行う必要があるため、メモリやストレージ、アクセス修飾子について、正しく理解しておく必要があると感じた。
次のチャプターはこちら
Discussion