在Rust中,可见性修饰符控制模块元素(结构体、函数、常量等)的访问。默认情况下,在模块中声明的所有内容都是私有的(仅在该模块内可访问)。存在以下特定修饰符:
pub:使元素变为公共(可从任何外部模块访问)。pub(crate):可见性限制在当前crate(包)内。pub(super):可见性限制在父模块内。pub(in path):可见性限制在特定路径内。示例:
mod foo { pub struct Bar { pub x: i32, // 字段在任何地方可用 y: i32, // 字段是私有的 } pub(crate) fn crate_fn() {} pub(super) fn super_fn() {} fn private_fn() {} }
与C++或Java的主要区别在于,没有单独的protected级别,并且可访问性在模块/路径级别而不是类层次结构中严格控制。
问题: 如果结构体声明为pub struct Foo,它的私有字段在同一项目的另一个模块中可用吗?
经常的回答: 是的,因为结构是公共的。
正确答案: 不,只有结构体(Foo)本身将变得可见,其字段仅在字段也用pub修饰时可见。没有pub的字段仍然是私有的,即使结构体本身是公共的。
示例:
mod foo { pub struct Bar { pub x: i32, y: i32, } } fn main() { let bar = foo::Bar { x: 1, y: 2 }; // 错误:字段`y`不可用 }
故事
在一个大型项目中,通过pub公开导出了结构体,但默认情况下将字段设为私有。其他模块无法直接创建结构的实例,唯一的解决方案是写额外的构造函数或将所需字段声明为pub。这导致在最终完善之前API出现了失败。
故事
该库中的一位开发者仅使用pub(crate)修饰符为函数,假设能够从使用该库的二进制项目中调用。但是,这些函数在外部的二进制crate中不可用,这在集成时造成了问题。
故事
在一个API服务器的插件中,为结构使用了pub(super),但一段时间后需要从其他模块访问它们;由于可见性设置,迫使在多个地方彻底重写模块,以确保所需的可见性而不破坏封装。