[英]How can I make the proxy type just for implementing some trait for it?
我要实现一些国外的特质( ToSql
和FromSql
从diesel
为外类型(箱) chrono::Duration
从chrono
箱)。 我这样做:
pub struct ChronoDurationProxy(pub chrono::Duration);
然后,我为此ChronoDurationProxy
类型实现了所需的特征。 但是,我希望用户不要太在意代理类型。 因此,在这种情况下,我所能做的唯一的事情就是实现了deref
特质。 但是我被困住了,因为我不太了解Deref
和AsRef
之间的区别。 因此,我同时实现了这两种方法,但我真的不知道是否应该这样做:
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.