英文:
Why can't Rust access private fields when a struct is in a different module?
问题
constructors
|---------src
| |----------lib.rs
| |----------constructor_file.rs
|
|----------Cargo.toml
|----------main.rs
lib.rs
pub mod constructor_file;
constructor_file.rs
pub struct Person {
name: String,
age: u32,
}
impl Person {
pub fn new(name: String, age: u32) -> Person {
Person { name, age }
}
pub fn show(self) {
println!("Name: {}, Age: {}", self.name, self.age);
}
}
main.rs
use constructor_lib::constructor_file::Person;
fn main() {
let person = Person { name: "Alice".to_string(), age: 33 };
person.show();
let person2 = Person::new("Bob".to_string(), 99);
person2.show();
}
Cargo.toml
[package]
name = "constructor_lib"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "constructor_exe"
path = "main.rs"
The above project is giving me the following build error
C:\git\Rust examples\constructors>cargo build
Compiling constructor_lib v0.1.0 (C:\git\Rust examples\constructors)
error[E0451]: field `name` of struct `Person` is private
--> main.rs:4:27
|
4 | let person = Person { name: "Alice".to_string(), age: 33 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ private field
error[E0451]: field `age` of struct `Person` is private
--> main.rs:4:54
|
4 | let person = Person { name: "Alice".to_string(), age: 33 };
| ^^^^^^^ private field
For more information about this error, try `rustc --explain E0451`.
error: could not compile `constructor_lib` due to 2 previous errors
C:\git\Rust examples\constructors>
Why doesn't this error show up when I keep Person
in the same file as main.rs
?
main.rs
//use constructor_lib::constructor_file::Person;
pub struct Person {
name: String,
age: u32,
}
impl Person {
pub fn new(name: String, age: u32) -> Person {
Person { name, age }
}
pub fn show(self) {
println!("Name: {}, Age: {}", self.name, self.age);
}
}
fn main() {
let person = Person { name: "Alice".to_string(), age: 33 };
person.show();
let person2 = Person::new("Bob".to_string(), 99);
person2.show();
}
英文:
constructors
|---------src
| |----------lib.rs
| |----------constructor_file.rs
|
|----------Cargo.toml
|----------main.rs
lib.rs
pub mod constructor_file;
constructor_file.rs
pub struct Person {
name: String,
age: u32,
}
impl Person {
pub fn new(name: String, age: u32) -> Person {
Person { name, age }
}
pub fn show(self)
{
println!("Name: {}, Age: {}", self.name, self.age);
}
}
main.rs
use constructor_lib::constructor_file::Person;
fn main() {
let person = Person { name: "Alice".to_string(), age: 33 };
person.show();
let person2 = Person::new("Bob".to_string(), 99 );
person2.show();
}
cargo.toml
[package]
name = "constructor_lib"
version = "0.1.0"
edition = "2021"
[[bin]]
name="constructor_exe"
path="main.rs"
The above project is giving me the following build error
C:\git\Rust examples\constructors>cargo build
Compiling constructor_lib v0.1.0 (C:\git\Rust examples\constructors)
error[E0451]: field `name` of struct `Person` is private
--> main.rs:4:27
|
4 | let person = Person { name: "Alice".to_string(), age: 33 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ private field
error[E0451]: field `age` of struct `Person` is private
--> main.rs:4:54
|
4 | let person = Person { name: "Alice".to_string(), age: 33 };
| ^^^^^^^ private field
For more information about this error, try `rustc --explain E0451`.
error: could not compile `constructor_lib` due to 2 previous errors
C:\git\Rust examples\constructors>
Why doesn't this error show up when I keep Person
in the same file as main.rs
?
main.rs
//use constructor_lib::constructor_file::Person;
pub struct Person {
name: String,
age: u32,
}
impl Person {
pub fn new(name: String, age: u32) -> Person {
Person { name, age }
}
pub fn show(self)
{
println!("Name: {}, Age: {}", self.name, self.age);
}
}
fn main() {
let person = Person { name: "Alice".to_string(), age: 33 };
person.show();
let person2 = Person::new("Bob".to_string(), 99 );
person2.show();
}
答案1
得分: 3
> 如果一个项是私有的,它可以被当前模块及其子模块访问。
如果结构体是在 main.rs
中定义的,那么 main.rs
是“模块或其子模块”的一部分,因此私有字段是可访问的。
如果结构体是在子模块中定义的,那么 main.rs
不是“模块或其子模块”的一部分,私有字段是不可访问的。
正如书中也有记录的,与许多其他编程语言不同,因为 Rust 的隐私基线非常严格,你可以更灵活地定义可见性,而不仅仅是“公共”的。
特别地,你可以将一个符号定义为 pub(super)
以使其从父模块中访问,以及 pub(crate)
以使其从整个 crate 中访问。
在许多语言中(例如 Java),默认情况类似于 pub(crate)
,而“私有”的访问必须被选择。在 Rust 中,情况正好相反,因为“私有”是默认的(尽管比 Java 的 private
权限宽松一些,我认为)。
英文:
Because that's how visibility works in Rust?
> If an item is private, it may be accessed by the current module and its descendants.
If the structure is defined in main.rs
, then main.rs
is part of "the module or its descendant", thus private fields are accessible.
If the structure is defined in a sub-module, then main.rs
is not part of "the module or its descendant", and private fields are not accessible.
As also documented in the book, and unlike many other languages, because Rust's privacy baseline is so restrictive you have a lot more flexibility in defining visibility than just "public".
Notably, you can define a symbol as pub(super)
to make it accessible from the parent module, and pub(crate)
to be accessible from the entire crate.
In many languages (e.g. java) the default is something like pub(crate)
, and "private" has to be opted in. In Rust, it's the other way around, "private" is the default (although it's a bit more relaxed than Java's own private
, I think).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论