How to restrict the construction of struct?

前端 未结 1 1478
遇见更好的自我
遇见更好的自我 2021-02-19 09:00

Is it possible to forbid creating an instances directly from member initialization?

e.g.

pub struct Person {
    name: String,
    age: u8,
}

impl Perso         


        
相关标签:
1条回答
  • 2021-02-19 09:09

    No, you cannot create that struct from member initialization and therefore your question is already the answer.

    This is because members are by default private and cannot be used directly. Only the immediate module and its submodules can access private fields, functions, ... (see the book about visibility).

    mod foo {
        pub struct Person {
            name: String,
            age: u8,
        }
    
        impl Person {
            pub fn new(age: u8, name: String) -> Person {
                if age < 18 {
                    panic!("Can not create instance");
                }
                Person { age, name }
            }
        }
    }
    
    use foo::Person; // imagine foo is an external crate
    
    fn main() {
        let p = Person {
            name: String::from("Peter"),
            age: 8,
        };
    }
    
    error[E0451]: field `name` of struct `Foo::Person` is private
    error[E0451]: field `age` of struct `Foo::Person` is private
    

    On the other hand, if you want to make it possible to create an instance by member initialization, use the pub keyword in front of all members.

    pub struct Person {
        pub name: String,
        pub age: u8,
    }
    

    Sometimes it's useful to let the user of your crate access the members directly, but you want to restrict the creation of an instance to your "constructors". Just add a private field.

    pub struct Person {
        pub name: String,
        pub age: u8,
        _private: ()
    }
    

    Because you cannot access _private, you cannot create an instance of Person directly.

    Also the _private field prevents creating a struct via the update syntax, so this fails:

    /// same code from above
    
    fn main() {
        let p = Person::new(8, String::from("Peter"));
        let p2 = Person { age: 10, ..p };
    }
    
    error[E0451]: field `_private` of struct `foo::Person` is private
      --> src/main.rs:27:34
       |
    27 |     let p2 = Person { age: 10, ..p };
       |                                  ^ field `_private` is private
    
    0 讨论(0)
提交回复
热议问题