Структури, модули

13 октомври 2022

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Административни неща

Структури

Структури

Синтаксис

1 2 3 4 5
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
fn main() {}

Структури

Създаване на инстанция

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
        sign_in_count: 10,
    };
}
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
        sign_in_count: 10,
    };
}

Структури

Достъп до полета

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
Иванчо, ivan40@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
}

Структури

Достъп до полета

Полетата се достъпват по същия начин и през референция.
Автоматично се правят необходимия брой дереференцирания.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
Иванчо, ivan40@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
}

Структури

Промяна на полетата

Можем да променяме стойността на полетата, ако инстанцията е дефинирана като mut.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let mut user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

user.email = "ivan40.ivanov@abv.bg".to_string();

println!("{}, {}", user.username, user.email);
Иванчо, ivan40.ivanov@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let mut user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

user.email = "ivan40.ivanov@abv.bg".to_string();

println!("{}, {}", user.username, user.email);
}

Структури

Преместване на структури

По подразбиране структурите се преместват (защото не имплементират Copy).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1;

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
error[E0382]: borrow of moved value: `user1` --> src/bin/main_b3c03fba678cada8014f8bd9534eee85648a700d.rs:16:44 | 8 | let user1 = User { | ----- move occurs because `user1` has type `User`, which does not implement the `Copy` trait ... 14 | let user2 = user1; | ----- value moved here 15 | 16 | println!("user1 = {}, {}", user1.username, user1.email); | ^^^^^^^^^^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1;

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
}

Структури

Клониране на структури

За да можем да създаваме копия на нашата структура, тя трябва да имплементира trait-а Clone.
Чрез атрибута #[derive(Clone)] компилатора автоматично ще ни създаде имплементация на Clone.
Аналогично #[derive(Copy)] ще имплементира Copy - но трябва всички полета да са Copy.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#[derive(Clone)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
user1 = Иванчо, ivan40@abv.bg user2 = Иванчо, ivan40@abv.bg
fn main() {
#[derive(Clone)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
}

Структури

Принтиране на структури

Аналогично можем да използваме атрибута #[derive(Debug)] за да получим имплементация на trait-а Debug.
Това ни позволява да принтираме нашата структура с println! инползвайки placeholder {:?}.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#[derive(Clone, Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {:?}", user1);
println!("user2 = {:?}", user2);
user1 = User { username: "Иванчо", email: "ivan40@abv.bg", sign_in_count: 10 } user2 = User { username: "Иванчо", email: "ivan40@abv.bg", sign_in_count: 10 }
fn main() {
#[derive(Clone, Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {:?}", user1);
println!("user2 = {:?}", user2);
}

Структури

Struct update синтаксис

Можем да дадем стойност само на част от полетата и останалите да попълним от друга инстанция

1 2 3 4 5 6 7 8 9 10 11 12
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{:?}", hacker);
User { username: "Иванчо", email: "hackerman@l33t.hax", sign_in_count: 10 }
#[derive(Debug)]
struct User { username: String, email: String, sign_in_count: u64 }
fn main() {
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{:?}", hacker);
}

Структури

Struct update синтаксис

Това ще премести полетата от оригиналната инстанция

1 2 3 4 5 6 7 8 9 10 11 12 13
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{:?}", hacker);
println!("{:?}", user);
error[E0382]: borrow of partially moved value: `user` --> src/bin/main_99773612f004f2399763eb71a56006b2f8c4c270.rs:16:18 | 10 | let hacker = User { | ______________- 11 | | email: String::from("hackerman@l33t.hax"), 12 | | ..user 13 | | }; | |_- value partially moved here ... 16 | println!("{:?}", user); | ^^^^ value borrowed here after partial move | = note: partial move occurs because `user.username` has type `String`, which does not implement the `Copy` trait = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
#[derive(Debug)]
struct User { username: String, email: String, sign_in_count: u64 }
fn main() {
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{:?}", hacker);
println!("{:?}", user);
}

Структури

Struct update синтаксис

Синтаксиса е удобен за попълване на стойности по подразбиране.
Напр. ако структурата имплементира трейта Default можем да използваме функцията default.

1 2 3 4 5 6
let user = User {
    username: String::from("Иванчо"),
    ..User::default()
};

println!("{:?}", user);
User { username: "Иванчо", email: "", sign_in_count: 0 }
#[derive(Debug, Default)]
struct User { username: String, email: String, sign_in_count: u64 }
fn main() {
let user = User {
    username: String::from("Иванчо"),
    ..User::default()
};

println!("{:?}", user);
}

Структури

Кратък синтаксис за създаване на структури

Често се случва стойността на поле да се задава чрез променлива със същото име. Има кратък синтаксис за това.

1 2 3 4 5 6 7 8 9 10 11 12 13
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

// пълен синтаксис
let rect = Rectangle {
    width: width,
    height: height,
};
fn main() {
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

// пълен синтаксис
let rect = Rectangle {
    width: width,
    height: height,
};
}

Структури

Кратък синтаксис за създаване на структури

Често се случва стойността на поле да се задава чрез променлива със същото име. Има кратък синтаксис за това.

1 2 3 4 5 6 7 8 9 10 11 12 13
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

// кратък синтаксис
let rect = Rectangle {
    width,
    height,
};
fn main() {
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

// кратък синтаксис
let rect = Rectangle {
    width,
    height,
};
}

Методи и асоциирани функции

Асоциирани функции

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

fn main() {
let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

fn main() {
let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
}

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват и като асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("area = {}", area);
}

Методи и асоциирани функции

Множество impl блокове

Позволено е декларирането на повече от един impl блок. Удобно е при групиране на методи.

1 2 3 4 5 6 7 8 9 10 11 12 13
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

impl Rectangle {
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

impl Rectangle {
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}
fn main() {}

Tuples

(преговор)

1 2 3 4 5
let tuple: (i32, u32, bool) = (1, 2, false);

println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
1 2 false
fn main() {
let tuple: (i32, u32, bool) = (1, 2, false);

println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
}

Tuple structs

Именувани кортежи

1 2 3 4 5
struct Color(f32, f32, f32);
struct Point(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);
let origin = Point(0.0, 0.0, 0.0);
fn main() {
struct Color(f32, f32, f32);
struct Point(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);
let origin = Point(0.0, 0.0, 0.0);
}

Tuple structs

Полетата се достъпват с .0, .1, и т.н., както при нормален tupple

1 2 3 4 5
struct Color(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
r: 0, g: 0, b: 0
fn main() {
struct Color(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
}

Tuple structs

Newtype wrapper

Tuple struct с едно поле често се използва за typesafe wrapper.
Това се нарича newtype struct или newtype wrapper.

1 2
#[derive(Debug, Clone, Copy)]
struct Token(u32);
#[derive(Debug, Clone, Copy)]
struct Token(u32);

fn main() {}

Празни структури

Възможна е декларацията на празни структури. Могат да се използват като маркери - големината им е 0 байта.

1 2 3 4 5
struct Electron {}
struct Proton;

let x = Electron {};
let y = Proton;
fn main() {
struct Electron {}
struct Proton;

let x = Electron {};
let y = Proton;
}

Модули

Модули

Модули

Модули

Нека си създадем библиотека:

$ cargo new communicator --lib

1 2 3 4
communicator
├── Cargo.toml
└── src
    └── lib.rs

Модули

Модули

Можем да дефинираме подмодули в същия файл

1 2 3 4 5 6 7 8 9
// src/lib.rs

mod network {
    fn init() { /* ... */ }
}

mod client {
    fn connect() { /* ... */ }
}
mod network {
    fn init() { /* ... */ }
}

mod client {
    fn connect() { /* ... */ }
}
fn main() {}

Модули

Можем да дефинираме подмодули и в отделни файлове

1 2 3 4 5 6
communicator
├── Cargo.toml
└── src
    ├── client.rs
    ├── lib.rs
    └── network.rs
1 2 3
// src/lib.rs
mod network;
mod client;

Модули

Можем да дефинираме подмодули и в отделни файлове

1 2 3 4 5 6
communicator
├── Cargo.toml
└── src
    ├── client.rs
    ├── lib.rs
    └── network.rs
1 2 3
// src/lib.rs
mod network;
mod client;

1 2
// src/network.rs
fn init() { /* ... */ }

1 2
// src/client.rs
fn connect() { /* ... */ }

Модули

Можем да имаме няколко нива на подмодули

1 2 3 4 5 6 7 8 9
// src/lib.rs

mod network {
    fn init() { /* ... */ }

    mod client {
        fn connect() { /* ... */ }
    }
}
mod network {
    fn init() { /* ... */ }

    mod client {
        fn connect() { /* ... */ }
    }
}

fn main() {}

Модули

Ако искаме да са в отделни файлове трябва да използваме директории

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    ├── lib.rs
    └── network
        ├── client.rs
        └── mod.rs
1 2
// src/lib.rs
mod network;
1 2 3
// src/network/mod.rs
mod client;
fn init() { /* ... */ }
1 2
// src/network/client.rs
fn connect() { /* ... */ }

Модули

network модула може да го сложим или в src/network/mod.rs, или в src/network.rs

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    ├── lib.rs
    ├── network.rs
    └── network
        └── client.rs
1 2
// src/lib.rs
mod network;
1 2 3
// src/network.rs
mod client;
fn init() { /* ... */ }
1 2
// src/network/client.rs
fn connect() { /* ... */ }

Достъп

В модул имаме директен достъп до всичко останало дефинирано в модула

1 2 3 4 5 6 7 8
mod client {
    fn connect() { /* ... */ }

    fn init() {
        // client::connect();
        connect();
    }
}
mod client {
    fn connect() { /* ... */ }

    fn init() {
        // client::connect();
        connect();
    }
}
fn main() {}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име или да го импортираме

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}

Достъп

Достъп

Достъп

Достъп

Mоже да използваме self::... или super::... за релативен път

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        super::client::connect();
    }
}

1 2 3 4 5 6 7 8 9 10 11
mod network {
    mod client {
        fn connect() { /* ... */ }
    }

    fn init() {
        self::client::connect();
        // или просто
        client::connect();
    }
}

#![allow(unused_imports)]
mod network {
    mod client {
pub
        fn connect() { /* ... */ }
    }

    fn init() {
        self::client::connect();
        // или просто
        client::connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
pub
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
pub
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
pub
    fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп: public и private

Ако искаме да използваме нещо извън модула, то трябва да е публично достъпно.

1 2 3 4 5 6 7 8 9 10
mod client {
    fn connect() { /* ... */ }

}

mod network {
    fn init() {
        crate::client::connect();
    }
}
error[E0603]: function `connect` is private --> src/bin/main_a59bcd63cbe47ef3a59fd915c88b119df8fb898a.rs:8:24 | 8 | crate::client::connect(); | ^^^^^^^ private function | note: the function `connect` is defined here --> src/bin/main_a59bcd63cbe47ef3a59fd915c88b119df8fb898a.rs:2:5 | 2 | fn connect() { /* ... */ } | ^^^^^^^^^^^^ For more information about this error, try `rustc --explain E0603`. error: could not compile `rust` due to previous error
mod client {
    fn connect() { /* ... */ }

}

mod network {
    fn init() {
        crate::client::connect();
    }
}
fn main() {}

Достъп: public и private

Ако искаме да използваме нещо извън модула, то трябва да е публично достъпно.

1 2 3 4 5 6 7 8 9 10
mod client {
    pub fn connect() { /* ... */ }
//  ^^^
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
mod client {
    pub fn connect() { /* ... */ }
//  ^^^
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
fn main() {}

Достъп: public и private

Достъп: public и private

Достъп: public и private

Структурата трябва да се маркира pub, за да е видима отвън

1 2 3 4 5 6 7 8 9 10 11 12
mod db {
    pub struct User {
//  ^^^
        username: String,
        email: String,
    }
}

use self::db::User;

fn main() {
}
#![allow(unused_imports)]
mod db {
    pub struct User {
//  ^^^
        username: String,
        email: String,
    }
}

use self::db::User;

fn main() {
}

Достъп: public и private

Полета също трябва да се отбележат с pub, за да се могат да се използват.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mod db {
    pub struct User {
        pub username: String,
        pub email: String,
//      ^^^
    }
}

use self::db::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
mod db {
    pub struct User {
        pub username: String,
        pub email: String,
//      ^^^
    }
}

use self::db::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

Без проблем може да достъпим private полета от същия модул в който е дефинирана структурата

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
mod db {
    pub struct User {
        username: String,
        email: String,
    }

    // свободна функция, не се намира в `impl` блок
    pub fn make_user(username: String, email: String) -> User {
        User { username, email }
    }
}

fn main() {
    let user = db::make_user(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
mod db {
    pub struct User {
        username: String,
        email: String,
    }

    // свободна функция, не се намира в `impl` блок
    pub fn make_user(username: String, email: String) -> User {
        User { username, email }
    }
}

fn main() {
    let user = db::make_user(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

Както и без проблем може да достъпим private полета на по-горен подмодул

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
mod db {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod make {
        use super::User;

        pub fn user(username: String, email: String) -> User {
            User { username, email }
        }
    }
}

fn main() {
    let user = db::make::user(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
mod db {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod make {
        use super::User;

        pub fn user(username: String, email: String) -> User {
            User { username, email }
        }
    }
}

fn main() {
    let user = db::make::user(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

Но ако модулите са съседни не можем

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mod db {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

    pub mod make {
        use super::dto::User;

        pub fn user(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
error[E0451]: field `username` of struct `User` is private --> src/bin/main_28d9be0010e27078d5ad972d5e012c043a3b352b.rs:13:20 | 13 | User { username, email } | ^^^^^^^^ private field error[E0451]: field `email` of struct `User` is private --> src/bin/main_28d9be0010e27078d5ad972d5e012c043a3b352b.rs:13:30 | 13 | User { username, email } | ^^^^^ private field For more information about this error, try `rustc --explain E0451`. error: could not compile `rust` due to 2 previous errors
mod db {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

    pub mod make {
        use super::dto::User;

        pub fn user(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
fn main() {}

Достъп: public и private

Тези правила важат и за tuple structs

1 2 3 4 5 6 7 8 9
mod product {
    pub struct UserId(u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}
error[E0423]: cannot initialize a tuple struct which contains private fields --> src/bin/main_4ab3111369e2922d14fb54434dca1a25870e2bd1.rs:8:14 | 8 | let id = UserId(123); | ^^^^^^ | note: constructor is not visible here due to private fields --> src/bin/main_4ab3111369e2922d14fb54434dca1a25870e2bd1.rs:2:23 | 2 | pub struct UserId(u64); | ^^^ private field For more information about this error, try `rustc --explain E0423`. error: could not compile `rust` due to previous error
mod product {
    pub struct UserId(u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}

Достъп: public и private

Тези правила важат и за tuple structs

1 2 3 4 5 6 7 8 9
mod product {
    pub struct UserId(pub u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}
mod product {
    pub struct UserId(pub u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}

Въпроси