0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Effective-Rustlings-jp】Day 15:可視範囲を最小化しよう

Last updated at Posted at 2025-01-20

はじめに

こんにちは。細々とプログラミングをしているsotanengelです。
この記事は以下の記事の連載です。

他の連載記事 (詳細)

また本記事はEffective Rust(David Drysdale (著), 中田 秀基 (翻訳))を参考に作成されております。とてもいい書籍ですので興味を持った方は、ぜひ読んでみてください!

今日の内容

概要

Rustではデフォルトで構造体やメソッドがプライベートになっています。
pubをつけたときにどのような挙動になるか確認しましょう。

pubをつけた時の挙動を確認しよう

問(リンク)

コメントに沿って、適宜pubを付与してください。

コード (詳細)
mod my_mod {
    // TODO: この構造体のpublic_valueにだけアクセスできるようにしてください。
    struct MyStruct {
        public_value: i32,
        private_value: i32,
    }

    // TODO: newとpublic_method、get_private_valueをアクセスできるようにしてください。
    impl MyStruct {
        fn new(pub_val: i32, priv_val: i32) -> Self {
            MyStruct {
                public_value: pub_val,
                private_value: priv_val,
            }
        }

        fn private_method(&self) {
            println!(
                "private_method called: public_value={}, private_value={}",
                self.public_value, self.private_value
            );
        }

        fn public_method(&self) {
            println!("public_method called: public_value={}", self.public_value);
            self.private_method();
        }

        fn get_private_value(&self) -> i32 {
            self.private_value
        }
    }

    // TODO: MyEnumにアクセスできるようにしてください。
    #[allow(dead_code)]
    enum MyEnum {
        A,
        B,
    }

    // TODO: MyTraitを実装したメソッド全てにアクセスできるようにしてください。
    trait MyTrait {
        fn trait_method(&self);
    }

    pub struct Implementer;

    impl MyTrait for Implementer {
        fn trait_method(&self) {
            println!("Implementer trait_method");
        }
    }
}

fn main() {
    // トレイトをスコープに導入する
    use my_mod::MyTrait;

    // MyStructの利用
    let s = my_mod::MyStruct::new(42, 7);
    println!("Public Value: {}", s.public_value);
    println!(
        "Accessed Private Value through getter: {}",
        s.get_private_value()
    );
    s.public_method();

    // MyEnumの利用
    let e = my_mod::MyEnum::A;
    match e {
        my_mod::MyEnum::A => println!("Matched variant A"),
        my_mod::MyEnum::B => println!("Matched variant B"),
    }

    // MyTraitの利用
    let impl_obj = my_mod::Implementer;
    // traitをスコープに入れているので、trait_methodが使用可能
    impl_obj.trait_method();
}

解答(リンク)

コード参照。

書籍の説明としては可視範囲は限りなく少なくがセオリーとしています。
理由としては、

  • 一度範囲をpubにすると元に戻すことが難しいため
  • 公開範囲が増えると将来的なメンテナンスの負担が増大するため

とのことでした。

コード (詳細)
mod my_mod {
    // パブリックな構造体
    pub struct MyStruct {
        pub public_value: i32, // パブリックなフィールド
        private_value: i32,    // 非公開のフィールド
    }

    impl MyStruct {
        // パブリックなコンストラクタ
        pub fn new(pub_val: i32, priv_val: i32) -> Self {
            MyStruct {
                public_value: pub_val,
                private_value: priv_val,
            }
        }

        // 非公開のメソッド
        fn private_method(&self) {
            println!(
                "private_method called: public_value={}, private_value={}",
                self.public_value, self.private_value
            );
        }

        // パブリックなメソッド
        pub fn public_method(&self) {
            println!("public_method called: public_value={}", self.public_value);
            self.private_method();
        }

        // 非公開フィールドにアクセスするためのパブリックメソッド
        pub fn get_private_value(&self) -> i32 {
            self.private_value
        }
    }

    // パブリックなenum
    #[allow(dead_code)]
    pub enum MyEnum {
        A,
        B,
    }

    // パブリックなトレイト
    pub trait MyTrait {
        fn trait_method(&self);
    }

    // トレイトを実装する構造体もpub
    pub struct Implementer;

    impl MyTrait for Implementer {
        fn trait_method(&self) {
            println!("Implementer trait_method");
        }
    }
}

fn main() {
    // トレイトをスコープに導入する
    use my_mod::MyTrait;

    // MyStructの利用
    let s = my_mod::MyStruct::new(42, 7);
    println!("Public Value: {}", s.public_value);
    println!(
        "Accessed Private Value through getter: {}",
        s.get_private_value()
    );
    s.public_method();

    // MyEnumの利用
    let e = my_mod::MyEnum::A;
    match e {
        my_mod::MyEnum::A => println!("Matched variant A"),
        my_mod::MyEnum::B => println!("Matched variant B"),
    }

    // MyTraitの利用
    let impl_obj = my_mod::Implementer;
    // traitをスコープに入れているので、trait_methodが使用可能
    impl_obj.trait_method();
}

さいごに

もしも本リポジトリで不備などあれば、リポジトリのissueやPRなどでご指摘いただければと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?