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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
use std::iter::ExactSizeIterator;
// Согласно принципам программирования, управляемого данными,
// мы инкапсулируем данные в простые классы (в Rust - структуры)-контейнеры.
// Все методы для работы с данными вынесены в отдельные структуры, которые
// могут быть использованы в другом коде и для других данных с минимальными
// изменениями.
// Таким образом, мы отделяем код от данных.
// Универсальная структура для хранения итератора общего типа
// (использование именно итератора (с известным размером) требуется
// характеристикой ExactSizeIterator в определении структуры.
struct Contents<T: ExactSizeIterator> {
contents: T,
}
// Структура данных почтового ящика
struct Mailbox<T: ExactSizeIterator> {
contents: Contents<T>,
unread: bool,
}
// Структура простого ящика
struct Box<T: ExactSizeIterator> {
volume: u8,
objects: Contents<T>,
}
// Проверяльщик содержимого контейнера.
// Структура реализует метод is_empty для проверки размера содержимого.
// Работает с нашей общей реализацией структуры-"контейнера" Contents
struct ContainerChecker {}
impl ContainerChecker {
fn is_empty<T: ExactSizeIterator>(data: &Contents<T>) -> bool {
return data.contents.len() == 0;
}
}
// Проверяльщик почтового ящика. Работает с почтовыми ящиками.
struct MailChecker {}
impl MailChecker {
fn check_mail<T: ExactSizeIterator>(mbox: &Mailbox<T>) {
if mbox.unread {
println!("Есть непрочитанные сообщения!");
} else {
println!("Непрочитанных писем нет.");
}
}
}
fn main() {
let box_contents = Contents {contents: [1, 2, 3, 4].iter()};
let b = Box { volume: 16, objects: box_contents};
if ContainerChecker::is_empty(&b.objects) {
println!("Коробка пуста!");
} else {
println!("В коробке что-то есть!");
}
let mail_contents = Contents {contents: ["Письмо", "Ещё письмо"].iter()};
let m = Mailbox { contents: mail_contents, unread: true };
// тот же проверяльщик, что использовался для проверки ящика, можно
// использовать и для почтового ящика - без всяких наследований.
if ContainerChecker::is_empty(&m.contents) {
println!("Почтовый ящик пуст!");
} else {
print!("В почтовом ящике есть письма; ");
MailChecker::check_mail(&m);
}
}
|