Реализация обобщенной характеристики контейнера

RustRustBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном задании у нас есть характеристика Contains, которая является обобщенной по типу контейнера и требует явного указания обобщенных типов при реализации для типа Container.

Примечание: Если лабораторная работа не уточняет имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/integer_types -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/function_syntax -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/expressions_statements -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/lifetime_specifiers -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/method_syntax -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/traits -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} rust/operator_overloading -.-> lab-99353{{"Реализация обобщенной характеристики контейнера"}} end

Проблема

Характеристика (trait), которая является обобщенной по типу контейнера, имеет требования к спецификации типов - пользователи характеристики должны указать все ее обобщенные типы.

В следующем примере характеристика Contains позволяет использовать обобщенные типы A и B. Затем характеристика реализуется для типа Container, при этом для A и B указывается i32, чтобы можно было использовать ее с fn difference().

Поскольку Contains является обобщенной, мы вынуждены явно указать все обобщенные типы для fn difference(). На практике мы хотим иметь способ выражать, что A и B определяются входным значением C. Как вы увидите в следующем разделе, ассоциированные типы предоставляют именно такую возможность.

struct Container(i32, i32);

// Характеристика, которая проверяет, хранятся ли 2 элемента внутри контейнера.
// Также извлекает первое или последнее значение.
trait Contains<A, B> {
    fn contains(&self, _: &A, _: &B) -> bool; // Явно требует `A` и `B`.
    fn first(&self) -> i32; // Не явно требует `A` или `B`.
    fn last(&self) -> i32;  // Не явно требует `A` или `B`.
}

impl Contains<i32, i32> for Container {
    // Возвращает true, если хранящиеся числа равны.
    fn contains(&self, number_1: &i32, number_2: &i32) -> bool {
        (&self.0 == number_1) && (&self.1 == number_2)
    }

    // Возвращает первое число.
    fn first(&self) -> i32 { self.0 }

    // Возвращает последнее число.
    fn last(&self) -> i32 { self.1 }
}

// `C` содержит `A` и `B`. Соответственно, повторно указывать `A` и
// `B` является неудобством.
fn difference<A, B, C>(container: &C) -> i32 where
    C: Contains<A, B> {
    container.last() - container.first()
}

fn main() {
    let number_1 = 3;
    let number_2 = 10;

    let container = Container(number_1, number_2);

    println!("Содержит ли контейнер {} и {}: {}",
        &number_1, &number_2,
        container.contains(&number_1, &number_2));
    println!("Первое число: {}", container.first());
    println!("Последнее число: {}", container.last());

    println!("Разница равна: {}", difference(&container));
}

Резюме

Поздравляем! Вы завершили лабораторную работу "Проблема". Вы можете практиковаться в других лабораторных работах в LabEx, чтобы улучшить свои навыки.