Nobiq
Nobiq

mapping・struct・配列

人ごと・リストのデータをまとめて扱う

これまでの変数は「値段」「累計」のようなひとつの値でした。今回は「人ごとのポイント」「商品のリスト」のような、たくさんの値をまとめて扱う道具を 3 つ覚えます。

mapping = 対応表

mapping(マッピング)は「AにはB」という対応表です。自販機に付けたポイントカードの台帳だと思ってください。「この住所の人は 30 ポイント」「あの住所の人は 10 ポイント」。

mapping(address => uint256) public points;

「住所(address)から整数(uint256)を引ける対応表を points と名づける」という意味です。使うときは points[住所] で読み書きします。

配列 = 順番つきのリスト

配列(はいれつ)は、順番に並べたリストです。メンバーの名簿や商品の陳列棚にあたります。

address[] public members;

「住所を並べたリストを members と名づける」。members.push(x) で末尾に追加できます。

struct = 自分で作るひとまとまり

struct(ストラクト)は、関連する値をひとまとめにした「自分で作る型」です。商品カードのイメージ——1 枚のカードに「名前」と「値段」が書いてある、あれです。

struct Item {
    string name;
    uint256 price;
}

3つを組み合わせた台帳

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract PointBook {
    mapping(address => uint256) public points;
    address[] public members;

    struct Item {
        string name;
        uint256 price;
    }
    Item[] public items;

    function addPoint() public {
        if (points[msg.sender] == 0) {
            members.push(msg.sender);
        }
        points[msg.sender] += 10;
    }

    function addItem(string calldata name, uint256 price) public {
        items.push(Item(name, price));
    }
}
  • addPoint = 操作した人(msg.sender)に 10 ポイント。if (条件) { } は「条件が成り立つときだけ実行」——初回(0 ポイント)の人だけ名簿に追加しています
    • なお Lab では操作が全員ぶん同じ代行送信者から届くため(第4回の note 参照)、「人別に分かれる」様子までは体験できません。書き方と意味を覚えましょう
  • Item[] public items; = 商品カード(struct)を並べた陳列棚。addItem("cola", 120) のように呼ぶと、カードを 1 枚作って棚に足します

データの置き場所(storage / memory / calldata)

第2〜3回で予告した話です。addItem の引数に付いていた calldata は、データの置き場所の指定です。

指定置き場所イメージ
storageブロックチェーン本体自販機に貼った、消えないメモ
memory処理中だけの作業台手に持ったメモ。処理が終わると捨てる
calldata受け取った引数そのまま届いた注文書を、書き換えずそのまま読む
  • 状態変数(contract 直下)は自動的に storage です
  • string や struct・配列を関数の引数や戻り値にするときだけmemorycalldata を明示するルールがあります(第7回の returns (string memory) もこれ)。迷ったら「受け取るだけなら calldata、加工するなら memory
  • uint256bool のような小さい値には不要です

今回覚えたこと

  • mapping = 対応表(points[住所] で読み書き)/ 配列 = 順番つきリスト(push で追加)/ struct = 値をひとまとめにした自作の型
  • storage / memory / calldata = データの置き場所。string 等を引数・戻り値にするときに明示する

次回は、設計図を引き継いで拡張する継承です。

:::tip Lab でやってみる PointBook をデプロイして、①addPoint を 2 回実行 ②members0 を入れて読むと、名簿の先頭の住所(0x...)が出ます ③その住所をコピーして points に入れて読むと 20 ④addItemcola120 を入れて実行 → items0 を入れて読むとカードの中身が見えます。操作方法: コントラクトを動かす :::