Что такое unit-подобные структуры Rust?

Unit-подобная структура (или “unit-like”, потому что она похожа на пустой кортеж (), иногда называемый “unit”) — это специальная структура на языке программирования Rust, которую мы объявляем без каких-либо полей. Определяется она с помощью ключевого слова struct, за которым следует имя unit-подобной структуры, а затем пара фигурных скобок без полей внутри, которые обычно опускаются при объявлении.

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

struct NameOfUnitStruct;

Зачем нужны unit-подобные структуры?

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

Например, вы можете определить unit-подобную структуру с целью представления конкретного варианта перечисления или реализации трейта (типажа) для типа, который не требует дополнительных данных.

Примеры использования unit-подобных структур

Использование unit-подобных структур в качестве вариантов перечислений

Ниже приведен типичный пример того, как вы можете использовать unit-подобную структуру в качестве варианта в перечислении:

#[derive(Debug)]
enum Animal {
    Cat,
    Dog,
    Horse,
    Mouse(String),
    Rat,
}

fn main() {
    let mouse = Animal::Mouse(String::from("Jerry"));
    let rat = Animal::Rat;

    println!("{:?}", mouse);
    println!("{:?}", rat);
}

В этом примере вариант Mouse перечисления Animal определен принимающим строковый параметр, в то время как вариант Rat представляет собой unit-подобную структуру и не содержит никаких дополнительных данных.

Использование unit-подобных структур для реализации трейтов

Вы также можете использовать unit-подобные структуры для реализации трейтов для типов, не имеющих полей. Например, вы можете определить трейт с названием Show, который требует от типа реализацию метода show(), выводящего какую-либо информацию о типе в консоль:

trait Show {
    fn show(&self);
}

struct Point {
    x: i32,
    y: i32,
}

impl Show for Point {
    fn show(&self) {
        println!("Point at ({}, {})", self.x, self.y);
    }
}

struct Line;

impl Show for Line {
    fn show(&self) {
        println!("Line");
    }
}

fn main() {
    let point = Point { x: 3, y: 4 };
    let line = Line;

    point.show();
    line.show();
}

В этом примере мы видим структуру Point, которая имеет два поля, x и y, и структуру Line, которая представляет из себя unit-подобную структуру без полей. Оба типа реализуют трейт Show и имеют метод show(), но реализация структуры Line не нуждается в доступе к каким-либо полям, ведь у этой структуры их нет.

Использование unit-подобных структур в качестве меток или плейсхолдеров

Unit-подобные структуры также могут вам пригодиться, когда вы хотите определить тип, имеющий определенное значение, но который не требует хранения каких-либо данных. Например, вы можете определить unit-подобную структуру, которая будет представлять конец потока данных или указать, что значение отсутствует или неизвестно.

struct EndOfStream;

fn main() {
    let mut stream: Vec<Result<i32, EndOfStream>> =
        vec![Ok(1), Ok(2), Ok(3), Ok(4), Ok(5), Err(EndOfStream)];

    while let Some(x) = stream.pop() {
        match x {
            Ok(x) => println!("{}", x),
            Err(_) => break,
        }
    }
}

В этом примере stream определяется как вектор значений Result, где вариант Ok представляет целочисленное значение, а вариант Err представляет собой unit-подобную структуру EndOfStream. Цикл while let перебирает элементы вектора stream и прерывается, когда ему повстречается вариант Err, указывающий на конец потока.


Завтра состоится открытое занятие «Особенности языка Rust в примерах». На уроке рассмотрим примеры кода, демонстрирующие ключевые особенности, преимущества и недостатки языка. Записаться можно на странице онлайн-курса "Rust Developer".

Комментарии (1)


  1. chicory-ru
    02.02.2023 06:00

    Не понял последний пример. Разве метод pop не удаляет с конца вектора? Он же с Err и начнет :)