Можно ли сделать мою собственную упаковку в виде коробки? - PullRequest
0 голосов
/ 03 июня 2018

Я заметил, что Box<T> реализует все, что T реализует и может использоваться прозрачно.Например:

let mut x: Box<Vec<u8>> = Box::new(Vec::new());
x.push(5);

Я бы хотел сделать то же самое.

Это один из вариантов использования:

Представьте себе, что я 'm пишу функции, которые работают с использованием оси X и оси Y. Я использую значения для изменения оси, которая имеет номера типа, но принадлежит только одной или другой оси.

Я бы хотел, чтобы мой компиляторпотерпеть неудачу, если я попытаюсь выполнить операции со значениями, которые не принадлежат хорошей оси.

Пример:

let x = AxisX(5);
let y = AxisY(3);
let result = x + y; // error: incompatible types

Я могу сделать это, создав структуру, которая будет переносить числа:

struct AxisX(i32);
struct AxisY(i32);

Но это не даст мне доступ ко всем методам, которые i32 предоставляет, например abs().Пример:

x.abs() + 3 // error: abs() does not exist
// ...maybe another error because I don't implement the addition...

Еще один возможный вариант использования:

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

1 Ответ

0 голосов
/ 03 июня 2018

Вы ищете std::ops::Deref:

В дополнение к использованию для явных операций разыменования с (одинарным) оператором * в неизменяемых контекстах, Deref также неявно используется компилятором во многих случаях.Этот механизм называется «Deref принуждение ».В изменяемых контекстах используется DerefMut.

Далее:

Если T реализует Deref<Target = U>, а x -значение типа T, затем:

  • В неизменяемых контекстах *x для типов без указателей эквивалентно *Deref::deref(&x).
  • Значения типа &Tприводятся к значениям типа &U
  • T неявно реализует все (неизменяемые) методы типа U.

Для получения более подробной информации посетите глава Язык программирования Rust , а также справочные разделы по оператору разыменования , разрешение метода и приведения типа .

Реализация Deref будет работать:

impl Deref for AxisX {
    type Target = i32;

    fn deref(&self) -> &i32 {
        &self.0
    }
}

x.abs() + 3

Это можно увидеть в действии на Playground .

Однако если вы вызываете функции из вашего базового типа (в данном случае i32), возвращаемый тип останется базовым типом.Поэтому

assert_eq!(AxisX(10).abs() + AxisY(20).abs(), 30);

пройдет.Чтобы решить эту проблему, вы можете перезаписать некоторые из тех методов, которые вам нужны:

impl AxisX {
    pub fn abs(&self) -> Self {
        // *self gets you `AxisX`
        // **self dereferences to i32
        AxisX((**self).abs())
    }
}

При этом вышеприведенный код завершается ошибкой. Взгляните на это в действии .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...