分解采用&Box的方法 和&T作为参数

问题描述 投票:2回答:1

我有一个方法,我需要使用特征参数调用(让我们称之为Listener)。原因是有时我之前已将此特征参数存储到父结构中,因此它位于Box内,有时不在。

所以我有两种方法:

  • fref<T>(t: &T) where T: Listener
  • fbox(t: &Box<dyn Listener>)

我希望他们俩都打电话给f(t: ??)。现在我复制了freffbox中的代码但有效但不好。所以我正在寻找一个f的签名,它可以从freffbox调用它来分解我的代码。我希望Box实施的一个特征相当于一个&(或者至少在某个地方找到一个共同点)。

我尝试了以下方法:

  • f<T>(t: &T) where T: Listener然后我不能从fbox打电话(Listener没有实施Box<dyn Listener>)。
  • 然后将调用从fbox内部更改为f(&*t)以取消我的Box<Listener>,但由于t不是Sized我不能。
  • 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);
}
rust polymorphism traits trait-objects
1个回答
4
投票

Listener是一个特征,所以Box<Listener>实际上是一个特征对象,Box<dyn Listener> - 不幸的是dyn关键字目前是可选的。 Box<dyn Listener>&Mouse都实施Deref,与Target相关联,实施Listener。在&Mouse的情况下,deref TargetMouse,但在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_refBox转换为引用以便调用它。特征对象案例仍然需要?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
{
}
© www.soinside.com 2019 - 2024. All rights reserved.