gpt4 book ai didi

rust - 我怎样才能使代理类型只是为了实现它的某些特征?

转载 作者:行者123 更新时间:2023-11-29 08:20:50 25 4
gpt4 key购买 nike

我想为外部类型(chrono::来自 chrono crate 的持续时间)。我这样做了:

pub struct ChronoDurationProxy(pub chrono::Duration);

然后我为这个 ChronoDurationProxy 类型实现了所需的特征。然而,我希望用户不要太在意代理类型。因此,在这种情况下,我唯一知道的就是为 deref 实现特征。但我被卡住了,因为我不太明白 DerefAsRef 之间的区别。所以,我实现了它们两个,但我真的不知道,我是否应该这样做:

impl AsRef<chrono::Duration> for ChronoDurationProxy {
fn as_ref(&self) -> &chrono::Duration {
&self.0
}
}

impl std::ops::Deref for ChronoDurationProxy {
type Target = chrono::Duration;

fn deref(&self) -> &Self::Target {
&self.0
}
}

我也不知道有任何其他方法可以提供这种类型代理的最透明方式,因此出现了这个问题。

最佳答案

TL;DR:它们是相反的东西。 Deref<T>说明如何取消引用类型 ( *T ), AsRef<T>解释什么是 &T .在您的情况下,您想使用 Borrow特征(而不是 AsRef ),如 this question 的答案中所述.


Deref告诉编译器当你取消引用你的类型时的结果是什么(在这种情况下你的类型就像一个智能指针):

struct UIntRef<'a>(&'a u32);

impl<'a> std::ops::Deref for UIntRef<'a> {
type Target = u32;

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

fn get_u32(_: u32) {}

fn main() {
let u = UIntRef(&42);

get_u32(*u); // I get an u32 when I deref an UIntRef
}

AsRef当事物具有作为内存“ View ”的意义时,是一种有用的抽象。例如,Vec或数组是内存中连续事物的集合。当您只需要读取那些东西时,您可以使用切片(AsRef<[T]> 是一个切片),它是内存的 View 。所以,一个数组和一个 Vec当您引用它们时,两者都可以看作是对内存的看法。因此你可以这样写:

fn get_view_on_things<T>(_: T)
where T: AsRef<[i32]> {}

fn main() {
get_view_on_things(&vec![1, 2, 3]);
get_view_on_things(&[1, 2, 3]);
}

要回答您的基本问题,您不能让事情对用户完全透明,这是一件好事。新类型是为了增加意义,而不是透明的:

struct Miles(f32);
struct Kms(f32);

fn take_a_distance(_: Miles) {}

fn main() {
take_a_distance(1.23);
// Cannot compile: What does the use wants ?

take_a_distance(Miles(1.23));
// Oh, now that's clear
}

但是,因为在这两种情况下您都可以获得相同类型的引用,所以您可以实现 Borrow对于您的新类型,如本例所示:

extern crate chrono;

use std::borrow::Borrow;

struct ChronoDurationProxy(chrono::Duration);

impl Borrow<chrono::Duration> for ChronoDurationProxy {
fn borrow(&self) -> &chrono::Duration {
&self.0
}
}

fn take_a_duration<T>(dur: T) where T: Borrow<chrono::Duration> {
let dur = dur.borrow(); // here we get a `&chrono::Duration`
println!("{:?}", dur)
}

fn main() {
let dur_1 = chrono::Duration::days(1);
let dur_2 = ChronoDurationProxy(dur_1);

take_a_duration(dur_1);
take_a_duration(dur_2);
}

关于rust - 我怎样才能使代理类型只是为了实现它的某些特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48872003/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com