rust - How to restrict the construction of struct?
问题描述
Is it possible to forbid creating an instances directly from member initialization?
e.g.
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 }
}
}
I can still use Person {age: 6, name:String::from("mike")}
to create instance. Is there anyway to avoid this?
解决方案
Answer to question
You cannot create that struct from member initialization, 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).
Your example works, because your function is in that certain scope.
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 `Person` is private
error[E0451]: field `age` of struct `Person` is private
Make it possible to create a struct from the outside
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,
}
Make it possible to access the fields, but not creating a struct from the outside
Please see KittenOverflows answer for a better approach to this.
--
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
推荐阅读
- python-3.x - 抓取网页上的特定表格,但每次都是空的
- git - 赫斯基钩子不在 Lerna monorepo 中运行
- c# - 如何自动更新 DataGridViewColumn?
- javascript - 使用 ASP.NET Razor 的 Ajax POST
- android - 如何在 RecyclerView 上使用 Firebase 存储显示多个用户的图像
- java - 接收数据时如何以图形方式更改数字?
- python - .map_diag(plt.hist,bins=30) - 对角线上没有直方图
- c# - 单击关闭按钮后,我在这一行出现 System.IO.IO.Exception 错误 'string machine_data = serialPort1.ReadTo("\u0003");'
- laravel - Laravel Echo + Websockets + 私人频道
- css - 如何使用 Bootstrap 4 和 Scss 将容器的宽度覆盖为 1440px 并使列同时响应