67 lines
No EOL
3.8 KiB
Markdown
67 lines
No EOL
3.8 KiB
Markdown
## 1. Суть трейта `Deref`
|
||
|
||
Трейт `std::ops::Deref` позволяет кастомизировать поведение оператора разыменования `*`.
|
||
Главная цель — сделать **Smart Pointers** (умные указатели) взаимозаменяемыми с обычными ссылками в клиентском коде.
|
||
|
||
**Механизм работы:**
|
||
Когда вы пишете `*y` для типа, реализующего `Deref`, Rust неявно преобразует это в:
|
||
|
||
rust
|
||
|
||
`*(y.deref())`
|
||
|
||
1. Вызывается метод `deref()`, который возвращает **ссылку** на внутреннее значение (`&Target`).
|
||
|
||
2. Затем происходит обычное разыменование `*` этой полученной ссылки.
|
||
|
||
|
||
> **Важно:** Метод `deref` возвращает именно ссылку, а не значение, чтобы не перемещать (move) владение данными из умного указателя.
|
||
|
||
## 2. Реализация
|
||
|
||
Для реализации собственного умного указателя (как в примере `MyBox<T>`) нужно:
|
||
|
||
- Указать ассоциированный тип `Target` (тип данных внутри обертки).
|
||
|
||
- Реализовать метод `deref`.
|
||
|
||
|
||
rust
|
||
|
||
`use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 // Возвращаем ссылку на поле кортежной структуры } }`
|
||
|
||
## 3. Deref Coercion (Неявное приведение)
|
||
|
||
Это механизм эргономики Rust, который автоматически преобразует ссылки при передаче аргументов в функции или методы.
|
||
|
||
- **Как работает:** Если тип `T` реализует `Deref<Target=U>`, то `&T` может быть неявно приведен к `&U`.
|
||
|
||
- **Цепочки:** Coercion работает рекурсивно.
|
||
|
||
- _Пример:_ `&MyBox<String>` → `deref` → `&String` → `deref` → `&str`.
|
||
|
||
- Это позволяет передавать `&MyBox<String>` в функцию, ожидающую `&str`.
|
||
|
||
- **Цена:** Работает на этапе компиляции (compile-time resolution), **runtime оверхеда нет**.
|
||
|
||
|
||
Без этого механизма код превратился бы в нагромождение символов: `&(*m)[..]` вместо простого `&m`.
|
||
|
||
## 4. Взаимодействие с изменяемостью (Mutability)
|
||
|
||
Для изменяемых ссылок существует зеркальный трейт `DerefMut`.
|
||
|
||
**Три правила приведения (Coercion rules):**
|
||
Rust применяет приведение типов в следующих случаях:
|
||
|
||
1. **`&T` → `&U`**: Если реализован `Deref` (Immutable to Immutable).
|
||
|
||
2. **`&mut T` → `&mut U`**: Если реализован `DerefMut` (Mutable to Mutable).
|
||
|
||
3. **`&mut T` → `&U`**: Если реализован `Deref` (Mutable to Immutable).
|
||
|
||
|
||
> **Критическое ограничение:** Приведение **Immutable (`&T`) → Mutable (`&mut U`)** невозможно.
|
||
> Это нарушило бы правила заимствования (Borrowing Rules), так как нельзя гарантировать уникальность создаваемой изменяемой ссылки, если исходная ссылка была неизменяемой (а их может быть много).
|
||
|
||
4. [https://doc.rust-lang.org/book/ch15-02-deref.html](https://doc.rust-lang.org/book/ch15-02-deref.html) |