Структури, модули, външни пакети

17 октомври 2019

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

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

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

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

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Съдържание

Съдържание

Съдържание

Съдържание

Съдържание

Структури

Структури

Синтаксис

1 2 3 4 5
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
#![allow(dead_code)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
fn main() {}

Структури

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

1 2 3 4 5
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};
#![allow(unused_variables)]
#![allow(dead_code)]
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
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
Иванчо, ivan40@abv.bg
#![allow(unused_variables)]
#![allow(dead_code)]
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,
};

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

Структури

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

Полетата се достъпват по същия начин и през референция

1 2 3 4 5 6 7 8 9
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
#![allow(unused_variables)]
#![allow(dead_code)]
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 user_ref = &user;

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

Компилаторът автоматично добавя *, докато крайния тип не съдържа желаното поле или ще хвърли грешка при компилация, ако няма такъв тип

Структури

Struct update syntax

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.username, hacker.email);
Иванчо, hackerman@l33t.hax
#![allow(unused_variables)]
#![allow(dead_code)]
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.username, hacker.email);
}

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

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

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,
        }
    }
}

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

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

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,
        }
    }
}

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

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

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,
        }
    }
}

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

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

1 2 3 4
let user = User::new(
    String::from("Иванчо"),
    String::from("ivan40@abv.bg"),
);
#![allow(unused_variables)]
#![allow(dead_code)]
struct User { username: String, email: String, sign_in_count: u64 }
impl User {
fn new(username: String, email: String) -> User {
User { username, email, sign_in_count: 0 }
}
}
fn main() {
let user = User::new(
    String::from("Иванчо"),
    String::from("ivan40@abv.bg"),
);
}

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

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

1 2 3 4
let user = User::new(
    String::from("Иванчо"),
    String::from("ivan40@abv.bg"),
);
#![allow(unused_variables)]
#![allow(dead_code)]
struct User { username: String, email: String, sign_in_count: u64 }
impl User {
fn new(username: String, email: String) -> User {
User { username, 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
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Rectangle {
        Rectangle { width, height }
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
struct Rectangle { width: f64, height: f64 }

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

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

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

1 2 3 4 5 6 7
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width: width,
    height: height,
};

Copy

#![allow(unused_variables)]
#![allow(dead_code)]
struct Rectangle { width: f64, height: f64 }
fn main() {
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width: width,
    height: height,
};
}

1 2 3 4 5 6 7
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width,
    height,
};

Copy

#![allow(unused_variables)]
#![allow(dead_code)]
struct Rectangle { width: f64, height: f64 }
fn main() {
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width,
    height,
};
}

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

Типа 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 }
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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 }
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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 }
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
struct Rectangle { width: f64, height: f64 }

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

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

Методи

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

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("{}", area);
6
#![allow(unused_variables)]
#![allow(dead_code)]
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);
}

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

Методи

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

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6
#![allow(unused_variables)]
#![allow(dead_code)]
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);
}

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

Методи

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

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6
#![allow(unused_variables)]
#![allow(dead_code)]
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);
}

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

Методи

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

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6
#![allow(unused_variables)]
#![allow(dead_code)]
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);
}

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

Множество 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 * (self.width + self.height)
    }
}

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

Множество 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 * (self.width + self.height)
    }
}

Можете ли да забележите грешката в кода?

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

Множество 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 * (self.width + self.height)
    }
}
error[E0277]: cannot multiply `f64` to `{integer}` --> src/bin/main_48e5b1756f5de31f54cd8e9c51305c10b1484936.rs:13:11 | 13 | 2 * (self.width + self.height) | ^ no implementation for `{integer} * f64` | = help: the trait `std::ops::Mul<f64>` is not implemented for `{integer}`
#![allow(unused_variables)]
#![allow(dead_code)]
struct Rectangle { width: f64, height: f64 }

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

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

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

Множество 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)
    }
}
#![allow(unused_variables)]
#![allow(dead_code)]
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() {}

Tuple structs

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

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

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
#![allow(unused_variables)]
fn main() {
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

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

Tuple structs

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

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

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

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
r: 0, g: 0, b: 0
#![allow(unused_variables)]
fn main() {
struct Color(i32, i32, i32);

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

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

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

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

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

let x = Electron {};
let y = Proton;
#![allow(unused_variables)]
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 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

mod client {
    fn connect() {
        // ...
    }
}
#![allow(dead_code)]
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

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

Модули

Дефиниране на модули във файл

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

mod client {
    fn connect() {
        // ...
    }
}
#![allow(dead_code)]
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

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

Двете connect функции са различни, тъй като са в отделни модули

Модули

Дефиниране на модули чрез файловата система

1 2 3 4
// src/lib.rs

mod network;
mod client;

1 2 3 4 5
// src/network.rs

fn connect() {
    // ...
}

Copy

#![allow(dead_code)]
// src/network.rs

fn connect() {
    // ...
}
fn main() {}

1 2 3 4 5
// src/client.rs

fn connect() {
    // ...
}

Copy

#![allow(dead_code)]
// src/client.rs

fn connect() {
    // ...
}
fn main() {}

Модули

Дефиниране на модули чрез файловата система

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

Подмодули

Дефиниране на подмодули във файл

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }

    mod client {
        fn connect() {
            // ...
        }
    }
}
#![allow(dead_code)]
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }

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

fn main() {}

Подмодули

Дефиниране на подмодули чрез файловата система

1 2 3
// src/lib.rs

mod network;

1 2 3 4 5 6 7
// src/network/mod.rs

mod client;

fn connect() {
    // ...
}

1 2 3 4 5
// src/network/client.rs

fn connect() {
    // ...
}

Copy

#![allow(dead_code)]
// src/network/client.rs

fn connect() {
    // ...
}
fn main() {}

Подмодули

Дефиниране на подмодули чрез файловата система

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

Подмодули

Дефиниране на подмодули чрез файловата система

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

Компилаторът търси за файловете MOD_NAME.rs или MOD_NAME/mod.rs

Достъп

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

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

    fn init() {
        // client::connect();
        connect();
    }
}
#![allow(dead_code)]
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();
    }
}

Достъп

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

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

mod network {
    fn init() {
        crate::client::connect();
    }
}
error[E0603]: function `connect` is private --> src/bin/main_539a02bbdae10004b3fb719e27ac122e0466c450.rs:8:24 | 8 | crate::client::connect(); | ^^^^^^^
#![allow(dead_code)]
mod client {
    fn connect() { /* ... */ }
}

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

Достъп

… и освен това то трябва да е публично достъпно (keyword pub)

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

mod network {
    fn init() {
        crate::client::connect();
    }
}
#![allow(dead_code)]
mod client {
    pub fn connect() { /* ... */ }
}

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

Достъп

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

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

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

    fn init() {
        connect();
    }
}
#![allow(dead_code)]
mod client {
    pub fn connect() { /* ... */ }
}

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

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

Достъп

Ако искаме да импортираме неща от подмодул, може да използваме use self::... за релативен път

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

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

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

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

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

Достъп

Ако искаме да импортираме неща от подмодул, може да използваме use self::... за релативен път

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

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

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

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

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

Също така има и use super::... за релативен път, който започва от по-горния модул

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

Нека да пуснем следния код

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

use self::product::User;

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

Достъп: public и private

Резултатът

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

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
error[E0451]: field `username` of struct `product::User` is private --> src/bin/main_0d3b14d7cbb234f13e06ce32ec05f23337e8e030.rs:14:9 | 14 | username: String::from("Иванчо"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `username` is private error[E0451]: field `email` of struct `product::User` is private --> src/bin/main_0d3b14d7cbb234f13e06ce32ec05f23337e8e030.rs:15:9 | 15 | email: String::from("ivan40@abv.bg"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `email` is private
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::product::User;

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

Достъп: public и private

Това може да се поправи като направим полетата публични

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

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    pub struct User {
        pub username: String,
        pub email: String,
    }
}

use self::product::User;

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

Достъп: public и private

Това може да се поправи като направим полетата публични

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

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    pub struct User {
        pub username: String,
        pub email: String,
    }
}

use self::product::User;

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

Както казахме, по подразбиране всичко е private за външни модули, включително и полета на структурата

Достъп: public и private

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

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

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

fn main() {
    let user = product::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    pub struct User {
        username: String,
        email: String,
    }

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

fn main() {
    let user = product::new(
        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 product {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod init_user {
        use super::User;

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

fn main() {
    let user = product::init_user::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod init_user {
        use super::User;

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

fn main() {
    let user = product::init_user::new(
        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 product {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

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

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
error[E0451]: field `username` of struct `product::dto::User` is private --> src/bin/main_32d0d16ed998784c78c8e88b67d5d7f6b4643aa6.rs:15:20 | 15 | User { username, email } | ^^^^^^^^ field `username` is private error[E0451]: field `email` of struct `product::dto::User` is private --> src/bin/main_32d0d16ed998784c78c8e88b67d5d7f6b4643aa6.rs:15:30 | 15 | User { username, email } | ^^^^^ field `email` is private
#![allow(dead_code)]
#![allow(unused_variables)]
mod product {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

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

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

Пакети

Пакети

Ще си направим игра за отгатване на число

$ cargo new number_guessing_game --bin

Пакети

Пакети

Пакети

Пакети

Трябва да си добавим пакета като зависомист на проекта ни

Cargo.toml

1 2 3 4 5 6 7
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["..."]
edition = "2018"

[dependencies]

Cargo.toml

1 2 3 4 5 6 7 8
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["..."]
edition = "2018"

[dependencies]
rand = "0.7.2"

Cargo.toml

Ако инсталирате cargo-edit чрез cargo install cargo-edit, може да използвате cargo add, което прави същото нещо автоматично с cargo add rand

Използване

След като се добави библиотека в [dependencies], може да се използва както всеки останал модул

1 2 3
use rand::*;

// ...

Документация

Документация

Имплементация

Live demo

Имплементация

Код от демото

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
use rand::prelude::*;
use std::io::{self, Write};

fn main() {
    // Generate a random number between 0 and 10
    let secret = rand::thread_rng().gen_range(0, 10_u32);
    let stdin = io::stdin();

    let tries = 5;
    println!("You have {} tries to guess the number. Good luck!", tries);

    for _ in 0..tries {
        // Note that stdout is frequently line-buffered by default so it may be necessary
        // to use io::stdout().flush() to ensure the output is emitted immediately.
        print!("Your guess: ");
        let _ = io::stdout().flush();

        let mut line = String::new();
        let _ = stdin.read_line(&mut line);

        // No error handling - panic if parsing fails
        let guess: u32 =
            line
            .trim()
            .parse()
            .unwrap();

        if secret < guess {
            println!("I am less than that");
        } else if secret > guess {
            println!("I am greater than that");
        } else {
            println!("Congratulations, you won!");
            return;
        }
    }

    println!("The number was {}", secret);
}

Въпроси