问题的答案
您无法通过成员初始化来创建该结构体,因为成员默认为私有且不能直接使用。只有直接模块及其子模块才能访问私有字段、函数等(请参阅关于可见性的书籍)。
您的示例有效,因为您的函数在该特定作用域中。
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;
fn main() {
let p = Person {
name: String::from("Peter"),
age: 8,
};
}
(游乐场)
error[E0451]: field `name` of struct `Person` is private
error[E0451]: field `age` of struct `Person` is private
使外部能够创建结构体
另一方面,如果您想通过成员初始化创建实例,则在所有成员前面使用pub
关键字。
pub struct Person {
pub name: String,
pub age: u8,
}
请注意,您可以用这种方式“跳过”
age >= 18
的要求,因此请明智使用。如果不希望这样做,请使用字段的get方法。
允许访问字段,但不要从外部创建结构体
请参见 KittenOverflows答案,了解另一种方法。
--
有时候让你的板条箱用户直接访问成员很有用,但你希望限制实例的创建只能通过“构造函数”进行。只需添加一个私有字段即可。
pub struct Person {
pub name: String,
pub age: u8,
_private: ()
}
由于您无法访问 _private
,因此无法直接创建 Person
实例。
_private
字段还防止通过update 语法创建结构体,因此会失败:
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
#[non_exhaustive]
。 - undefinednon_exhaustive
属性,它更适合这种情况。 唯一的区别在于更新语法,如果您需要,请在结构体上使用#[allow(clippy::manual_non_exhaustive)]
。 - undefined