Управление доступом с помощью ключевого слова pub

Мы исправили ошибки связанные с распределением кода. Но остались проблемы с использованием кода (функци не используются):

warning: function is never used: `connect`, #[warn(dead_code)] on by default
src/client.rs:1:1
  |
1 | fn connect() {
  | ^

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/mod.rs:1:1
  |
1 | fn connect() {
  | ^

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/server.rs:1:1
  |
1 | fn connect() {
  | ^

Почему имеют место эти ошибки? Библиотеку существуют для того, чтобы ими пользовались пользователи. Поэтому важно, чтобы проблемы с доступом к функционалу были решены.

Для того, чтобы понять почему существуют такие ошибки, а как важно их устранить, попробуем воспользоваться функционалом кода извне. Для этого создадим выполняемый проект в этой же директории. Создадим файл src/main.rs, который содержит:

Filename: src/main.rs

extern crate communicator;

fn main() {
    communicator::client::connect();
}

Мы сейчас использовали команду extern crate для того чтобы использовать функционал библиотеки communicator в нашей новой программе. Cargo использует файл src/main.rs, как точку доступа для бинарной программы, в то время, как src/lib.rs используется для библиотеки. Такая организация кода довольно-таки обычна. Большинство кода находится в библиотеках, а бинарный файл просто использует эту библиотеку. Результатом такой архитектуры является возможность другим программам также использовать функционал библиотеки.

Со стороны стороннего кода все что находится в библиотеке имеет пространство имён communicator (имя библиотеки) верхнего уровня. Всё остальное, это подчиненные модули.

Также обратите внимание, что когда мы используем внешние библиотеки с подомодулями, команда extern crate начинает искать модули с верхнего уровня.

В нашей программе бинарный файл вызывает библиотечную функцию connect из модуля client. Но при компиляции этого кода получим сообщении об ошибке:

error: module `client` is private
 --> src/main.rs:4:5
  |
4 |     communicator::client::connect();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Это сообщение говорит нам о том, что модуль client закрытый. Т.к. код в модуле закрытый по умолчанию и не используется внутри библиотеки - на это надо обратить внимание, т.к. это явная ошибка в организации кода.

После определения функции client::connect, как доступной (pub), не только сообщение об ошибке исчезнет, но и проподёт сообщение о том, что код не используется. Создания доступного кода в Rust даёт возможность его использования вне библиотеки. Когда какой-либо кода помечается как pub, компилятор больше не сообщает об неиспользованном коде, если даже он фактически не используется.

Сделать функции доступными

Для того, чтобы сделать что-либо доступным извне необходимо добавить ключевое слово pub в начало декларирования элемента кода. Для исправления ошибки мы добавить это спецификатор доступа перед определение имени модуля. :

Filename: src/lib.rs

pub mod client;

mod network;

Ключевое слово pub перед mod. Компиляция. Сообщение об ошибке:

error: function `connect` is private
 --> src/main.rs:4:5
  |
4 |     communicator::client::connect();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Сделаем исправления в определении функции в файле src/client.rs:

Filename: src/client.rs


# #![allow(unused_variables)]
#fn main() {
pub fn connect() {
}
#}

Снова компилируем cargo clean && cargo build снова:

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/mod.rs:1:1
  |
1 | fn connect() {
  | ^

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/server.rs:1:1
  |
1 | fn connect() {
  | ^

Код скомпилировался и предостережения о функции client::connect уже нет!

Вам решать, что делать с неиспользованным кодом, то ли открыть к нему доступ, то ли удалить.

В данном случае мы хотим, чтобы эти функции были доступны. Поэтому добавим pub там, где это необходимо:

Filename: src/network/mod.rs

pub fn connect() {
}

mod server;

Скомпилируем и проанализируем ошибки:

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/mod.rs:1:1
  |
1 | pub fn connect() {
  | ^

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/server.rs:1:1
  |
1 | fn connect() {
  | ^

Для того, чтобы открытые функции модуля были доступны, сам модуль должен быть доступен:

Filename: src/lib.rs

pub mod client;

pub mod network;

Новые сообщения компилятора:

warning: function is never used: `connect`, #[warn(dead_code)] on by default
 --> src/network/server.rs:1:1
  |
1 | fn connect() {
  | ^

Надеюсь, что теперь исправить последний недочёт программы Вам не составит труда.

Правила доступа

  1. Если элемент открытый, он должен быть открытый и все родительские модули тоже.
  2. Если элемент закрытый, он может быть доступен только из родительского модуля и из любых подчиненных модулей.

Примеры

Создадим новый проект библиотеки secret 7-5 src/lib.rs:

Filename: src/lib.rs

mod outermost {
    pub fn middle_function() {}

    fn middle_secret_function() {}

    mod inside {
        pub fn inner_function() {}

        fn secret_function() {}
    }
}

fn try_me() {
    outermost::middle_function();
    outermost::middle_secret_function();
    outermost::inside::inner_function();
    outermost::inside::secret_function();
}

Код 7-5: Примеры открытых и закрытый функций с ошибками

Перед компиляцией кода, попробуйте догадаться, где будет ошибка. Убедитесь в этом с помощью компиляции. Исправьте ошибки в коде!

Рассмотрим ошибки

Функция try_me находится на верхнем уровне модуля нашего проекта. Модуль outermost закрытый, но к его функциям может быть доступ, т.к. модуль верхнего уровня.

Вызов остальных двух функций вызовет ошибку, т.к. не применяются правила видимости. Пожалуйста, исправьте ошибку!

Исправление ошибок

Пожалуйста, попытайтесь поэкспериментировать с доступом к функциям и посмотрите на описания ошибок!

Далее, мы поговорим об использовании ключевого слова use.