Структури, модули, външни пакети
17 октомври 2019
Административни неща
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
- Елате в Discord канала: https://discord.gg/FCTNfbZ
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
- Елате в Discord канала: https://discord.gg/FCTNfbZ
- Регистрирайте се в https://fmi.rust-lang.bg!
Преговор
Преговор
- Присвояване и местене
Преговор
- Присвояване и местене
- Clone и Copy
Преговор
- Присвояване и местене
- Clone и Copy
- Собственост
Преговор
- Присвояване и местене
- Clone и Copy
- Собственост
- Референции
- референцията винаги сочи към валидна стойност
- една mutable референция XOR произволен брой immutable референции
Преговор
- Присвояване и местене
- Clone и Copy
- Собственост
- Референции
- референцията винаги сочи към валидна стойност
- една mutable референция XOR произволен брой immutable референции
- Низове (
String) и резени от низове (&str)
Преговор
- Присвояване и местене
- Clone и Copy
- Собственост
- Референции
- референцията винаги сочи към валидна стойност
- една mutable референция XOR произволен брой immutable референции
- Низове (
String) и резени от низове (&str) - Вектори (
Vec<T>) и резени от масиви (&[T])
Съдържание
Съдържание
- Структури
Съдържание
- Структури
- Методи
Съдържание
- Структури
- Методи
- Модули
Съдържание
- Структури
- Методи
- Модули
- Използване на пакети от crates.io
Структури

Структури
Синтаксис
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() {}
Структури
Създаване на инстанция
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,
};
}
Структури
Достъп до полета
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);
}
Структури
Достъп до полета
Полетата се достъпват по същия начин и през референция
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
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);
}
Методи и асоциирани функции
Асоциирани функции
struct User { ... }
impl User {
fn new(username: String, email: String) -> User {
User {
username: username,
email: email,
sign_in_count: 0,
}
}
}
Методи и асоциирани функции
Асоциирани функции
struct User { ... }
impl User {
fn new(username: String, email: String) -> User {
User {
username: username,
email: email,
sign_in_count: 0,
}
}
}
- разделение между данни и логика:
structблока съдържа само полетата на структурата- методи и функции се добавят в отделен
implблок
Методи и асоциирани функции
Асоциирани функции
struct User { ... }
impl User {
fn new(username: String, email: String) -> User {
User {
username: username,
email: email,
sign_in_count: 0,
}
}
}
- разделение между данни и логика:
structблока съдържа само полетата на структурата- методи и функции се добавят в отделен
implблок
- функцията
newсе нарича асоциирана функция - семантично еднаква със статичен метод от други езици
Методи и асоциирани функции
Асоциирани функции
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"),
);
}
Методи и асоциирани функции
Асоциирани функции
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"),
);
}
- когато викаме асоциирани функции като
new, трябва да ги префиксираме с името на структурата (User) и оператора::
Методи и асоциирани функции
Конструктори и деструктори
Методи и асоциирани функции
Конструктори и деструктори
- в Rust няма конструктори, а вместо това се използват асоциирани функции
Методи и асоциирани функции
Конструктори и деструктори
- в Rust няма конструктори, а вместо това се използват асоциирани функции
- често използвани имена за конструктори са
newfrom_*with_*
Методи и асоциирани функции
Конструктори и деструктори
- в Rust няма конструктори, а вместо това се използват асоциирани функции
- често използвани имена за конструктори са
newfrom_*with_*
- в Rust има деструктори, но за тях ще говорим по-късно
Методи и асоциирани функции
Още един пример
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() {}
Методи и асоциирани функции
Кратък синтаксис за създаване на структури
let width = 2.0;
let height = 3.0;
let rect = Rectangle {
width: width,
height: height,
};
#![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,
};
}
let width = 2.0;
let height = 3.0;
let rect = Rectangle {
width,
height,
};
#![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
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
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() {}
- достъпен само в
implблок
Методи и асоциирани функции
Типа Self
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() {}
- достъпен само в
implблок - alias на типа, за който имплементираме
Методи и асоциирани функции
Методи
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() {}
Методи и асоциирани функции
Методи
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() {}
- функция, която приема като първи аргумент
self,&self,&mut self(method receiver)
Методи и асоциирани функции
Методи
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() {}
- функция, която приема като първи аргумент
self,&self,&mut self(method receiver) selfе еквивалентно наself: Self
Методи и асоциирани функции
Методи
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() {}
- функция, която приема като първи аргумент
self,&self,&mut self(method receiver) selfе еквивалентно наself: Self&selfе еквивалентно наself: &Self
Методи и асоциирани функции
Методи
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() {}
- функция, която приема като първи аргумент
self,&self,&mut self(method receiver) selfе еквивалентно наself: Self&selfе еквивалентно наself: &Self&mut selfе еквивалентно наself: &mut Self
Методи и асоциирани функции
Методи
Методите могат да се използват като асоциирана функция
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);
}
Методи и асоциирани функции
Методи
Но могат и да се извикват със синтаксиса за методи
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);
}
Методи и асоциирани функции
Методи
Но могат и да се извикват със синтаксиса за методи
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);
}
- както полетата, методите се достъпват с
.
Методи и асоциирани функции
Методи
Но могат и да се извикват със синтаксиса за методи
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);
}
- както полетата, методите се достъпват с
. - компилаторът автоматично добавя
*,&или&mut, така че типа на аргумента да съвпадне с типа на method receiver-а
Методи и асоциирани функции
Множество impl блокове
Позволено е декларирането на повече от един impl блок. Удобно е при групиране на методи.
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 блок. Удобно е при групиране на методи.
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 блок. Удобно е при групиране на методи.
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 блок. Удобно е при групиране на методи.
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
Именувани кортежи
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, и т.н., както при нормален кортеж
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 байта.
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
communicator
├── Cargo.toml
└── src
└── lib.rs
Модули
Дефиниране на модули във файл
// 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() {}
Модули
Дефиниране на модули във файл
// 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 функции са различни, тъй като са в отделни модули
Модули
Дефиниране на модули чрез файловата система
// src/lib.rs
mod network;
mod client;
// src/network.rs
fn connect() {
// ...
}
#![allow(dead_code)]
// src/network.rs
fn connect() {
// ...
}
fn main() {}
// src/client.rs
fn connect() {
// ...
}
#![allow(dead_code)]
// src/client.rs
fn connect() {
// ...
}
fn main() {}Модули
Дефиниране на модули чрез файловата система
communicator
├── Cargo.toml
└── src
└── client.rs
└── lib.rs
└── network.rs
Подмодули
Дефиниране на подмодули във файл
// 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() {}
Подмодули
Дефиниране на подмодули чрез файловата система
// src/lib.rs
mod network;
// src/network/mod.rs
mod client;
fn connect() {
// ...
}
// src/network/client.rs
fn connect() {
// ...
}
#![allow(dead_code)]
// src/network/client.rs
fn connect() {
// ...
}
fn main() {}Подмодули
Дефиниране на подмодули чрез файловата система
communicator
├── Cargo.toml
└── src
└── lib.rs
└── network
└── client.rs
└── mod.rs
Подмодули
Дефиниране на подмодули чрез файловата система
communicator
├── Cargo.toml
└── src
└── lib.rs
└── network
└── client.rs
└── mod.rs
Компилаторът търси за файловете MOD_NAME.rs или MOD_NAME/mod.rs
Достъп
В модул имаме директен достъп до всичко останало дефинирано в модула
mod client {
fn connect() { /* ... */ }
fn init() {
// client::connect();
connect();
}
}
#![allow(dead_code)]
mod client {
fn connect() { /* ... */ }
fn init() {
// client::connect();
connect();
}
}
fn main() {}
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
- пълното име започва с име на crate-а или ключовата дума
crateако е дефинирано в нашия проект
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
- пълното име започва с име на crate-а или ключовата дума
crateако е дефинирано в нашия проект - след това следва пътя до item-а
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
- пълното име започва с име на crate-а или ключовата дума
crateако е дефинирано в нашия проект - след това следва пътя до item-а
crate::client::connectstd::vec::Vec
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
- пълното име започва с име на crate-а или ключовата дума
crateако е дефинирано в нашия проект - след това следва пътя до item-а
crate::client::connectstd::vec::Vec
- ако искаме да използваме повече от едно нещо
crate::client::{something, some_other_thing}
Достъп
- ако искаме да използваме нещо извън модула трябва да използваме пълното име
- пълното име започва с име на crate-а или ключовата дума
crateако е дефинирано в нашия проект - след това следва пътя до item-а
crate::client::connectstd::vec::Vec
- ако искаме да използваме повече от едно нещо
crate::client::{something, some_other_thing} - или ако искаме да използваме всичко от даден модул
crate::client::*(удобно заpreludeмодули)
Достъп
Ако искаме да използваме нещо извън модула трябва да използваме пълното име
mod client {
fn connect() { /* ... */ }
}
mod network {
fn init() {
crate::client::connect();
}
}
Достъп
Ако искаме да използваме нещо извън модула трябва да използваме пълното име..
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)
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 за да импортираме имена от друг модул
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::... за релативен път
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::... за релативен път
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
- по подразбиране всичко е private
Достъп: public и private
- по подразбиране всичко е private
- за да се направи нещо достъпно извън модула, в който е дефинирано, се използва
pub
Достъп: public и private
- по подразбиране всичко е private
- за да се направи нещо достъпно извън модула, в който е дефинирано, се използва
pub - винаги има достъп до нещата, които са дефинирани в текущия модул, или по-нагоре в йерархията
Достъп: public и private
Нека да пуснем следния код
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
Резултатът
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
Това може да се поправи като направим полетата публични
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
Това може да се поправи като направим полетата публични
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 полета от същия модул в който е дефинирана структурата
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 полета в подмодул..
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
..но не и ако модулите са съседи
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
Пакети
- трябва ни генератор на случайни числа
Пакети
- трябва ни генератор на случайни числа
- в стандартната библиотека няма такъв
Пакети
- трябва ни генератор на случайни числа
- в стандартната библиотека няма такъв
- може да потърсим в https://crates.io/
Пакети
- трябва ни генератор на случайни числа
- в стандартната библиотека няма такъв
- може да потърсим в https://crates.io/
- https://crates.io/crates/rand
Трябва да си добавим пакета като зависомист на проекта ни
Cargo.toml
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["..."]
edition = "2018"
[dependencies]
Cargo.toml
[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], може да се използва както всеки останал модул
use rand::*;
// ...
Документация
- https://docs.rs/ - документация за всички пакети от crates.io
Документация
- https://docs.rs/ - документация за всички пакети от crates.io
- https://docs.rs/rand/
Имплементация
Live demo
Имплементация
Код от демото
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);
}