Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Обобщённые типы данных

С помощью обобщений можно абстрагироваться от конкретного типа поля. Возвращаясь к упражнению из предыдущего сегмента:

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub trait Logger {
    /// Записывает сообщение с заданным уровнем подробности.
    fn log(&self, verbosity: u8, message: &str);
}

struct StderrLogger;

impl Logger for StderrLogger {
    fn log(&self, verbosity: u8, message: &str) {
        eprintln!("[stderr] verbosity={verbosity}: {message}");
    }
}

struct StdoutLogger;

impl Logger for StdoutLogger {
    fn log(&self, verbosity: u8, message: &str) {
        println!("[stdout] verbosity={verbosity}: {message}");
    }
}

/// Записывает только сообщения до заданного уровня подробности.
struct VerbosityFilter<L> {
    max_verbosity: u8,
    inner: L,
}

impl<L: Logger> Logger for VerbosityFilter<L> {
    fn log(&self, verbosity: u8, message: &str) {
        if verbosity <= self.max_verbosity {
            self.inner.log(verbosity, message);
        }
    }
}

fn main() {
    let err = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
    err.log(5, "FYI");
    err.log(2, "Uhoh");

    let out = VerbosityFilter { max_verbosity: 3, inner: StdoutLogger };
    out.log(5, "FYI");
    out.log(2, "Uhoh");
}
This slide should take about 10 minutes.
  • Вопрос: Почему L указан дважды в impl<L: Logger> .. VerbosityFilter<L>? Разве это не избыточно?
    • Это потому, что это обобщённый блок реализации для обобщённого типа. Они независимо обобщены.
    • Это означает, что эти методы определены для любого L.
    • Можно написать impl VerbosityFilter<StderrLogger> { .. }.
      • VerbosityFilter по-прежнему обобщён, и можно использовать VerbosityFilter<f64>, но методы в этом блоке будут доступны только для VerbosityFilter<StderrLogger>.
  • Обратите внимание, что мы не задаём ограничение трейта для самого типа VerbosityFilter. Туда тоже можно поставить ограничения, но в Rust обычно ограничения трейтов указывают только в блоках impl.