summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 2623171eb47d8c371fcc4f81e258d1d5cdfbb4bb (plain)
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
75
use std::iter::ExactSizeIterator;

// Согласно принципам программирования, управляемого данными,
// мы инкапсулируем данные в простые классы (в Rust - структуры)-контейнеры.
// Все методы для работы с данными вынесены в отдельные структуры, которые
// могут быть использованы в другом коде и для других данных с минимальными
// изменениями.
// Таким образом, мы отделяем код от данных.

// Универсальная структура для хранения итератора общего типа 
// (использование именно итератора (с известным размером) требуется 
// характеристикой ExactSizeIterator в определении структуры.
struct Contents<T: ExactSizeIterator> {
    contents: T,
}

// Структура данных почтового ящика
struct Mailbox<T: ExactSizeIterator> {
    contents: Contents<T>,
    unread: bool,
}

// Структура простого ящика
#[allow(dead_code)] // чтобы компилятор не ругался на неиспользуемое поле
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);
    }
}