Programmingライブラリ開発者 / Rustライブラリ開発者

Rustで構造体のフィールドへのアクセス制御はどのように実現されており、モジュールの可視性とどのように関連していますか?モジュールの外部で構造体を使用する際にエラーを最小限に抑えるために、公的APIを適切に構成するにはどうすればよいですか?

Hintsage AIアシスタントで面接を突破

答え。

問題の歴史:

C++やJavaのような言語では、アクセス修飾子(public、private、protected)がクラスのメンバーの可視性を確保しますが、かなり柔軟であり、APIの誤った使用を防ぐことはあまりありません。Rustでは、初期のバージョンからアクセス制御のシステムが厳格かつ明示的なモジュールベースにされており、内部の詳細が外部に漏れるのを制限しています。

問題:

構造体は外部コードから部分的に隠す必要があることがよくあります。例えば、フィールドはプライベートであり、外部にはメソッドだけを公開します。アクセスを制限しないと、構造体の不変条件が意図せずに壊れる可能性があります(例えば、内部のVecを直接公開すること)。構造体を無思慮に公開すると、APIが脆弱になります。

解決策:

Rustでは、すべてがデフォルトでプライベートです。キーワードpubは明示的なエクスポートに使用されます。構造体は個別に可視化することができ、フィールドは隠されます。メソッドは個別にpubまたはプライベートとして宣言されます。さらに、pub(crate)やpub(super)のような非標準の形は、アクセスレベルを微調整することを可能にします。

コード例:

mod domain { pub struct User { pub name: String, age: u32, // プライベートフィールド } impl User { pub fn new(name: String, age: u32) -> Self { Self { name, age } } pub fn age(&self) -> u32 { self.age } } } use domain::User; fn main() { let u = User::new("Eve".to_string(), 24); println!("{} {}", u.name, u.age()); // u.age — アクセスエラー!フィールドはモジュールの外で閉じられています }

主な特徴:

  • デフォルトではすべてプライベートで、フィールドや関数を含む
  • pubは明示的に選択された要素を外部に公開する
  • pub(crate)、pub(super)は大規模なプロジェクトのためにアクセスを柔軟に設定する

罠のある質問。

構造体をpubにして、すべてのフィールドをプライベートのままにすることはできますか?モジュールの外でそのインスタンスをどのように作成しますか?

はい。通常そうします:構造体はpubであり、フィールドはプライベートで、公開コンストラクタ(例えば、pub fn new...)を通じてのみ作成されます。

pub struct Fooと宣言すると、構造体のフィールドは外部コードで見ることができますか?

いいえ、デフォルトでは各フィールドは依然としてプライベートです—フィールドに対してpubを明示的に指定する必要があります。pub structはタイプを見えるようにするだけです。

enumに対してpubは同様に機能しますか?

enumの場合、pubはすべてのバリエーションに適用されますが、バリエーション内の関連データ(例えば、Variant(value: T)のフィールド)については、内部をアクセス可能にしたい場合はpubを明示的に指定する必要があります。

典型的なエラーとアンチパターン

  • シンプルさのためにすべてのフィールドをpubにし、カプセル化を破る
  • 外部モジュールからプライベートフィールドに直接アクセスしようとする(コンパイルエラー)
  • すべてのフィールドが閉じられている場合、構造体の構築/変更のためのパブリックメソッドを作成するのを忘れる

実際の例

ネガティブケース

ライブラリ内で構造体はpub struct Configとして宣言され、すべてのフィールドもpubになっている—ユーザーが"見える"ようにするため。結果として、外部の任意のコードが状態を任意に変更し、不変条件を壊し、突然のpanicが発生する可能性があります。

利点:

  • ユーザーにとって最大のオープン性と柔軟性

欠点:

  • カプセル化の破壊
  • APIの移行やバージョン管理が難しくなる
  • フィールドの不適切な使用によるバグの増加

ポジティブケース

構造体Configはpubで、すべてのフィールドはプライベートです。設定はビルダーメソッド、デフォルトコンストラクタ、またはセッター/ゲッター関数を通じてのみ可能です。モジュールの外部で不変条件を壊すことはできません。

利点:

  • APIがクリーンで、不変条件が管理されている
  • 従来の互換性を維持しやすい

欠点:

  • 複雑な構造体の場合、より多くのコードが必要(メソッド、コンストラクタ、テスト)