Rust на примерах - страница 4

стр.

>#[derive(Debug)]

>struct Person<'a> {

>name: &'a str,

>age: u8

>}

>fn main() {

>let name = "Peter";

>let age = 27;

>let peter = Person { name, age };

>// Pretty print

>println!("{:#?}", peter);

>}

>הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Можно вручную реализовать fmt::Display для управления отображением.

fmt::Debug выглядит не очень компактно и красиво, поэтому полезно настраивать внешний вид информации, которая будет напечатана. Это можно сделать реализовав типаж fmt::Display вручную, который использует маркер {} для печати. Его реализация выглядит следующим образом:

>#![allow(unused)]

>fn main() {

>// Импортируем (с помощью `use`) модуль `fmt`, чтобы мы могли его использовать.

>use std::fmt;


>// Определяем структуру, для которой будет реализован `fmt::Display`.

>// Это простая кортежная структура c именем `Structure`, которая хранит в себе `i32`.

>struct Structure(i32);


>// Чтобы была возможность использовать маркер `{}`

>// `типаж (trait) fmt::Display` должен быть реализован вручную

>// для данного типа.

>impl fmt::Display for Structure {

>// Этот типаж требует реализацию метода `fmt` с данной сигнатурой:

>fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

>// Записываем первый элемент в предоставленный выходной поток: `f`.

>// Возвращаем `fmt::Result`, который показывает выполнилась операция

>// успешно или нет. Обратите внимание на то, что синтаксис `write!`

>// похож на синтаксис `println!`.

>write!(f, "{}", self.0)

>}

>}

>}

Вывод fmt::Display может быть более чистым, чем fmt::Debug, но может быть проблемой для стандартной библиотеки (std). Как нестандартные типы должны отображаться? Например, если std предоставляет единый стиль вывода для Vec, каким этот вывод должен быть? Любой из этих двух?

   • Vec: /:/etc:/home/username:/bin (разделитель :)

   • Vec: 1,2,3 (разделитель ,)

Нет, потому что не существует идеального стиля вывода для всех типов, поэтому std не может его предоставить. fmt::Display не реализован для Vec или для других обобщённых контейнеров. Для этих случаев подойдёт fmt::Debug.

Это не проблема, потому что для любых новых контейнеров, типы которых не обобщённые, может быть реализован fmt::Display.

>use std::fmt; // Импортируем `fmt`

>// Структура, которая хранит в себе два числа.

>// Вывод типажа `Debug` добавлен для сравнения с `Display`.

>#[derive(Debug)]

>struct MinMax(i64, i64);

>// Реализуем `Display` для `MinMax`.

>impl fmt::Display for MinMax {

>fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

>// Используем `self.номер`, чтобы получить доступ к каждому полю структуры.

>write!(f, "({}, {})", self.0, self.1)

>}

>}

>// Объявим структуру с именованными полями, для сравнения

>#[derive(Debug)]

>struct Point2D {

>x: f64,

>y: f64,

>}

>// По аналогии, реализуем `Display` для Point2D

>impl fmt::Display for Point2D {

>fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

>// Обращаться к полям структуры Point2D будет по имени

>write!(f, "x: {}, y: {}", self.x, self.y)

>}

>}

>fn main() {

>let minmax = MinMax(0, 14);

>println!("Сравниваем структуры:");

>println!("Display: {}", minmax);

>println!("Debug: {:?}", minmax);

>let big_range = MinMax(-300, 300);

>let small_range = MinMax(-3, 3);

>println!("Большой диапазон - {big} и маленький диапазон {small}",

>small = small_range,

>big = big_range);

>let point = Point2D { x: 3.3, y: 7.2 };

>println!("Сравниваем точки:");

>println!("Display: {}", point);

>println!("Debug: {:?}", point);

>// Ошибка. Типажи `Debug` и `Display` были реализованы, но `{:b}`

>// необходима реализация `fmt::Binary`. Следующий код не сработает.

>// println!("Как выглядит Point2D в виде двоичного кода: {:b}?", point);