フレンズ
この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::B
と0x42::C
の両方が0x42::A
のフレンドと見なされます。
address 0x42 {
module a {
friend 0x42::b;
friend 0x42::c;
}
}
useス
テートメントとは異なり、friend
はモジュールスコープでのみ宣言出来、式ブロックスコープでは宣言出来ません。friend
宣言は、トップレベル構造 (use
、function
、struct
等)が許可されている場所であればどこへでも配置出来ます。ただし、読みやすさを考慮して、フレンド宣言はモジュール定義の先頭近くへ配置することを推奨します。
注: フレンドシップの概念は 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::a
friends0x2::b
friends0x2::c
friends0x2::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'が重複しています。モジュール内のフレンド宣言は一意である必要が有ります。
}
}