From b05088b9f58712f7babee5e40f608bbbc326846c Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 19 Jan 2025 07:35:24 +0000 Subject: [PATCH] Be clear that the methods-and-traits exercise does not require generics When teaching the course, I got a little tripped up thinking students would need to make the `VerbosityFilter` generic over `Logger`. Let's be clearer that this is not required, and will be described later. This also updates the generic-types slide to repeat the exercise, completing that thought. --- src/generics/generic-data.md | 56 +++++++++++++++++------------- src/methods-and-traits/exercise.md | 9 ++--- src/methods-and-traits/exercise.rs | 2 +- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/generics/generic-data.md b/src/generics/generic-data.md index 35ba2e3486b8..a4bd82bafb0c 100644 --- a/src/generics/generic-data.md +++ b/src/generics/generic-data.md @@ -4,46 +4,54 @@ minutes: 10 # Generic Data Types -You can use generics to abstract over the concrete field type: +You can use generics to abstract over the concrete field type. Returning to the +exercise for the previous segment: ```rust,editable -#[derive(Debug)] -struct Point { - x: T, - y: T, +pub trait Logger { + /// Log a message at the given verbosity level. + fn log(&self, verbosity: u8, message: &str); } -impl Point { - fn coords(&self) -> (&T, &T) { - (&self.x, &self.y) +struct StderrLogger; + +impl Logger for StderrLogger { + fn log(&self, verbosity: u8, message: &str) { + eprintln!("verbosity={verbosity}: {message}"); } +} + +/// Only log messages up to the given verbosity level. +struct VerbosityFilter { + max_verbosity: u8, + inner: L, +} - fn set_x(&mut self, x: T) { - self.x = x; +impl Logger for VerbosityFilter { + fn log(&self, verbosity: u8, message: &str) { + if verbosity <= self.max_verbosity { + self.inner.log(verbosity, message); + } } } fn main() { - let integer = Point { x: 5, y: 10 }; - let float = Point { x: 1.0, y: 4.0 }; - println!("{integer:?} and {float:?}"); - println!("coords: {:?}", integer.coords()); + let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger }; + logger.log(5, "FYI"); + logger.log(2, "Uhoh"); } ```
-- _Q:_ Why `T` is specified twice in `impl Point {}`? Isn't that - redundant? +- _Q:_ Why `L` is specified twice in `impl .. VerbosityFilter`? + Isn't that redundant? - This is because it is a generic implementation section for generic type. They are independently generic. - - It means these methods are defined for any `T`. - - It is possible to write `impl Point { .. }`. - - `Point` is still generic and you can use `Point`, but methods in this - block will only be available for `Point`. - -- Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`. Update the - code to allow points that have elements of different types, by using two type - variables, e.g., `T` and `U`. + - It means these methods are defined for any `L`. + - It is possible to write `impl VerbosityFilter { .. }`. + - `VerbosityFilter` is still generic and you can use `VerbosityFilter`, + but methods in this block will only be available for + `Point`.
diff --git a/src/methods-and-traits/exercise.md b/src/methods-and-traits/exercise.md index d7d8830c6278..56a14b5eb36f 100644 --- a/src/methods-and-traits/exercise.md +++ b/src/methods-and-traits/exercise.md @@ -1,5 +1,5 @@ --- -minutes: 20 +minutes: 15 --- # Exercise: Logger Trait @@ -14,13 +14,14 @@ verbosity. Your task is to write a `VerbosityFilter` type that will ignore messages above a maximum verbosity. This is a common pattern: a struct wrapping a trait implementation and -implementing that same trait, adding behavior in the process. What other kinds -of wrappers might be useful in a logging utility? +implementing that same trait, adding behavior in the process. In the "Generics" +segment this afternoon, we will see how to make the wrapper generic over the +wrapped type. ```rust,compile_fail {{#include exercise.rs:setup}} -// TODO: Define and implement `VerbosityFilter`. +// TODO: Implement the `Logger` trait for `VerbosityFilter`. {{#include exercise.rs:main}} ``` diff --git a/src/methods-and-traits/exercise.rs b/src/methods-and-traits/exercise.rs index f7b9fa035cbb..2bb8e4702ce2 100644 --- a/src/methods-and-traits/exercise.rs +++ b/src/methods-and-traits/exercise.rs @@ -26,13 +26,13 @@ impl Logger for StderrLogger { eprintln!("verbosity={verbosity}: {message}"); } } -// ANCHOR_END: setup /// Only log messages up to the given verbosity level. struct VerbosityFilter { max_verbosity: u8, inner: StderrLogger, } +// ANCHOR_END: setup impl Logger for VerbosityFilter { fn log(&self, verbosity: u8, message: &str) {