2

我有一个需要使用特征参数调用的方法(我们称之为Listener)。原因是有时我之前已将此特征参数存储到父结构中,因此它位于 a 内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但后来我不能从 fboxListener不是由Box<dyn Listener>)调用。
  • 然后将呼叫从内部fbox更改f(&*t)为取消装箱我的Box<Listener>但因为t不是Size我不能。

  • 写作f<T>(t: &T) where T: std::borrow::Borrow<Listener>,但后来我不能从frefBorrow不是由实现Listener)调用

  • AsRef<Listener>
  • Deref 游乐场的最后一次尝试:
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);
}
4

1 回答 1

4

Listener是一个特征,所以Box<Listener>实际上一个特征对象,Box<dyn Listener>- 不幸的是dyn关键字当前是可选的。Box<dyn Listener>和implement ,具有实现的&Mouse关联类型。在deref的情况下是,但在它的情况下是未知对象,大小未知DerefTargetListener&MouseTargetMouseBox<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将 aBox转入引用以便调用它。特征对象的?Sized情况仍然需要非约束,并且仍然有效,因为值总是在指针后面:

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
{
}
于 2019-03-01T22:21:57.677 回答