Можно ли иметь модуль, который частично доступен снаружи ящика и частично только внутри ящика?
Есть ли лучший способ, чем просто положить все в один и тот же модуль?
sub_module.rs
pub struct GiantStruct { /* */ }
impl GiantStruct {
// this method needs to be called from outside of the crate.
pub fn do_stuff( /* */ ) { /* */ };
}
lib.rs
pub mod sub_module;
use sub_module::GiantStruct;
pub struct GiantStructBuilder{ /* */ }
impl GiantStructBuilder{
pub fn new_giant_struct(&mut self) -> GiantStruct {
// Do stuff depending on the fields of the current
// GiantStructBuilder
}
}
Проблема с GiantStructBuilder::new_giant_struct()
; этот метод должен создать новый GiantStruct
но для этого вам либо нужно pub fn new() -> GiantStruct
Внутри sub_module.rs
или все поля GiantStruct
должен быть публичным. Оба варианта позволяют получить доступ снаружи моего ящика.
При написании этого вопроса я понял, что могу сделать что-то вроде этого:
sub_module.rs
pub struct GiantStruct { /* */ }
impl GiantStruct {
// now you can't call this method without an appropriate
// GiantStructBuilder
pub fn new(&mut GiantStructBuilder) -> GiantStruct { /* */ };
pub fn do_stuff( /* */ ) { /* */ };
}
Однако это кажется действительно нелогичным, так как обычно вызывающая сторона - это то, что действует, в то время как переменные функции - это то, на что воздействуют, что, очевидно, не тот случай, когда это делается так. Поэтому я все еще хотел бы знать, есть ли лучший способ...
1 ответ
Вы можете использовать недавно стабилизированный pub(restricted)
конфиденциальность
Это позволит вам предоставлять типы / функции только ограниченному дереву модулей, например
pub struct GiantStruct { /* */ }
impl GiantStruct {
// Only visible to functions in the same crate
pub(crate) fn new() -> GiantStruct { /* */ };
// this method needs to be called from outside of the crate.
pub fn do_stuff( /* */ ) { /* */ };
}
Или вы можете применить это к полям на вашем GiantStruct
чтобы позволить вам создать его из GiantStructBuilder
:
pub struct GiantStruct {
pub(crate) my_field: u32,
}
Вместо crate
Вы также можете использовать super
указать, что это только для родительского модуля.