我有一个方法,我需要使用特征参数调用(让我们称之为Listener
)。原因是有时我之前已将此特征参数存储到父结构中,因此它位于Box
内,有时不在。
所以我有两种方法:
fref<T>(t: &T) where T: Listener
fbox(t: &Box<dyn Listener>)
我希望他们俩都打电话给f(t: ??)
。现在我复制了fref
和fbox
中的代码但有效但不好。所以我正在寻找一个f
的签名,它可以从fref
和fbox
调用它来分解我的代码。我希望Box
实施的一个特征相当于一个&
(或者至少在某个地方找到一个共同点)。
我尝试了以下方法:
f<T>(t: &T) where T: Listener
然后我不能从fbox
打电话(Listener
没有实施Box<dyn Listener>
)。fbox
内部更改为f(&*t)
以取消我的Box<Listener>
,但由于t
不是Size
d我不能。f<T>(t: &T) where T: std::borrow::Borrow<Listener>
然后我不能从fref
打电话(Borrow
没有实施Listener
)AsRef<Listener>
相同Deref
playground的最后一次尝试:trait Listener {}
struct Mouse {}
impl Listener for Mouse {}
fn fbox(t: &Box<Listener>) {
f(t);
}
fn fref<T>(t: &T)
where
T: Listener,
{
f(t);
}
fn f<T>(_t: &T)
where
T: std::ops::Deref<Target = Listener>,
{
}
fn create_listener() -> impl Listener {
Mouse {}
}
fn main() {
let mouse = create_listener();
let box_mouse: Box<Listener> = Box::new(Mouse {});
fref(&mouse);
fbox(&box_mouse);
}
Listener
是一个特征,所以Box<Listener>
实际上是一个特征对象,Box<dyn Listener>
- 不幸的是dyn
关键字目前是可选的。 Box<dyn Listener>
和&Mouse
都实施Deref
,与Target
相关联,实施Listener
。在&Mouse
的情况下,deref Target
是Mouse
,但在Box<dyn Listener>
的情况下,它是一个未知的对象,dyn Listener
大小不明。
要捕获所有这些信息,您可以像这样编写f
:
fn f<T, L>(_listener: &T)
where
T: Deref<Target = L>,
L: Listener + ?Sized
{
}
并从每个函数调用它,如下所示:
fn fbox(listener: &Box<dyn Listener>) {
f(listener);
}
fn fref<L>(listener: &L)
where
L: Listener
{
f(&listener);
}
另一种可能更简单的方法是放弃Deref
约束并使用普通引用。使用Box::as_ref
将Box
转换为引用以便调用它。特征对象案例仍然需要?Sized
un-constraint,并且仍然有效,因为值总是在指针后面:
fn fbox(listener: &Box<dyn Listener>) {
f(listener.as_ref());
}
fn fref<L>(listener: &L) where L: Listener {
f(listener);
}
fn f<L>(_listener: &L)
where
L: Listener + ?Sized
{
}