Ответ 1
Для того, чтобы item был экспортирован из библиотечного ящика, должен быть хотя бы один путь, ведущий к нему, в котором каждый компонент является общедоступным. Это означает, что все, что вам нужно, чтобы сделать объект общедоступным в вашем ящике, но не экспортироваться из ящика (я буду называть это "внутренним" с этого момента, чтобы подражать терминологии С#) заключается в том, чтобы поместить его в частный модуль под корневым ящиком.
Однако это решение является довольно ограничительным. Что делать, если вы хотите иметь модуль с экспортированными функциями и внутренними функциями? Чтобы экспортировать некоторые функции, нам нужно сделать модуль общедоступным, и это означает, что все публичные элементы в этом модуле также будут экспортированы.
Так как Rust 1.18, есть решение, адаптированное к такому сценарию: pub(restricted)
. Эта функция позволяет указать "как публичный" элемент. Синтаксис довольно гибкий (вы можете сделать элемент видимым для конкретного дерева модулей, а не для всего контейнера), но если вы хотите сохранить его простым, pub(crate)
сделает элемент доступным в любом месте ящика, но не к другому ящики (эквивалентные internal
в С#).
Например, предположим, что мы хотим иметь модуль util
, в котором foo
экспортируется (как mycrate::util::foo
), bar
является внутренним, а baz
является приватным для модуля. Код может выглядеть так:
pub mod util {
pub fn foo() {
unimplemented!()
}
pub(crate) fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
Если вы застряли на до-1.18 ржавчины, обходной путь, но это немного неуклюже. Он включает определение всех ваших элементов в частных модулях и реэкспорт только тех, которые вы хотите опубликовать (с pub use
) в общедоступных модулях, которые содержат только реэкспорт. Вот как выглядит пример выше:
pub mod util {
pub use util_impl::foo;
}
mod util_impl {
pub fn foo() {
unimplemented!()
}
pub fn bar() {
unimplemented!()
}
fn baz() {
unimplemented!()
}
}
Это не просто читать и понимать не просто, но не охватывает все ситуации, в которых можно использовать pub
. Например, как вы могли бы сделать некоторые поля экспортируемой структуры доступными в других модулях в одном ящике без их экспорта? Единственным вариантом было бы выставить оболочку с одним частным полем, тип которого является структурой, имеющей общедоступные поля; это прекрасно работает, если вы хотите скрыть все поля из других ящиков, но не для того, чтобы выставить некоторые поля и сделать некоторые другие поля внутри одной и той же структуры.