繁体   English   中英

如何使代理类型仅用于实现某些特征?

[英]How can I make the proxy type just for implementing some trait for it?

我要实现一些国外的特质( ToSqlFromSqldiesel为外类型(箱) chrono::Durationchrono箱)。 我这样做:

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 ),如关于此问题的答案所述。


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是有用的抽象。 例如, Vec或数组是内存中连续的事物的集合。 当您只需要阅读这些内容时,可以使用一个切片( AsRef<[T]>是切片),该切片是内存上的视图 因此,当您引用数组和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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM