メインコンテンツまでスキップ

フレンズ

このfriend構文は、現在のモジュールによって信頼されるモジュールを宣言するため使用されます。信頼されたモジュールは、現在のモジュールで定義されているpublic(friend)可視性を持つ任意の関数を呼び出す事が出来ます。関数の可視性の詳細は関数可視性 セクションを参照して下さい。

フレンド宣言

モジュールはフレンド宣言文を使って他のモジュールをフレンドとして宣言する事が出来る。以下の形式で。

  • friend <address::name> — 以下の例の様な完全修飾モジュール名を使用したフレンド宣言、または

    address 0x42 {
    module a {
    friend 0x42::b;
    }
    }
  • friend <module-name-alias> — モジュール名エイリアスを使用したフレンド宣言。モジュールエイリアスはuse ステートメントを介して導入されます。

    address 0x42 {
    module a {
    use 0x42::b;
    friend b;
    }
    }

モジュールには複数のフレンド宣言がある場合があり、すべてのフレンドモジュールの結合によってフレンドリストが形成されます。以下の例では、0x42::B0x42::Cの両方が0x42::Aのフレンドと見なされます。

address 0x42 {
module a {
friend 0x42::b;
friend 0x42::c;
}
}

useステートメントとは異なり、friendはモジュールスコープでのみ宣言出来、式ブロックスコープでは宣言出来ません。friend宣言は、トップレベル構造 (usefunctionstruct等)が許可されている場所であればどこへでも配置出来ます。ただし、読みやすさを考慮して、フレンド宣言はモジュール定義の先頭近くへ配置することを推奨します。

注: フレンドシップの概念は Moveスクリプトには適用されません。

  • Moveスクリプトではfriendモジュールを宣言出来ません。これは、スクリプトで定義された関数を呼び出すメカニズムがないため、意味が無いと見なされるためです。
  • Moveモジュールはfriendスクリプトを宣言出来ません。(スクリプトがグローバルストレージに公開されることのない一時的なコードスニペットなので)

フレンド宣言ルール

フレンド宣言は以下のルールへ従います:

  • モジュール自体はフレンドとして宣言する事は出来ません。

    address 0x42 {
    module m { friend Self; // エラー! }
    // ^^^^ モジュール自体をフレンドとして宣言する事は出来ません。
    }

    address 0x43 {
    module m { friend 0x43::M; // エラー! }
    // ^^^^^^^ モジュール自体をフレンドとして宣言する事は出来ません。
    }
  • フレンドモジュールはコンパイラによって認識されている必要が有ります。

    address 0x42 {
    module m { friend 0x42::nonexistent; // ERROR! }
    // ^^^^^^^^^^^^^^^^^ '0x42::nonexistent'はバウンドされていないモジュールです。
    }
  • フレンドモジュールは同じアカウントアドレス内に有る必要があります。(注: これは技術的な要件ではなく、後で緩和される可能性のある方針決定です。)

    address 0x42 {
    module m {}
    }

    address 0x43 {
    module n { friend 0x42::m; // エラー! }
    // ^^^^^^^ 現在のアドレス以外のモジュールをフレンドとして宣言する事は出来ません
    }
  • フレンド関係は循環的なモジュール依存関係を作成出来ません。

 フレンド関係では循環は許可されません。例えば0x2::afriends0x2::bfriends0x2::cfriends0x2::aという関係は許可されません。より一般的には、フレンド モジュールを宣言すると、フレンド モジュールに現在のモジュールへの依存関係が追加されます (フレンドが現在のモジュール内の関数を呼び出す事が目的であるため)。そのフレンドモジュールが直接または推移的にすでに使用されている場合は、依存関係の循環が作成されます。

address 0x2 {
module a {
use 0x2::c;
friend 0x2::b;

public fun a() {
c::c()
}
}

module b {
friend 0x2::c; // エラー!
// ^^^^^^ このフレンド関係は依存関係の循環を作成します:'0x2::b'は'0x2::a'のフレンドであり、'0x2::c'は'0x2::b'のフレンドです。
}

module c {
public fun c() {}
}
}
  • モジュールのフレンドリストへ重複を含める事は出来ません。

    address 0x42 {
    module a {}

    module m {
    use 0x42::a as aliased_a;
    friend 0x42::A;
    friend aliased_a; // エラー!
    // ^^^^^^^^^ フレンド宣言'0x42::a'が重複しています。モジュール内のフレンド宣言は一意である必要が有ります。
    }
    }