Rust 因子分解法;盒子<;T>;及;T作为论据

Rust 因子分解法;盒子<;T>;及;T作为论据,rust,polymorphism,traits,trait-objects,Rust,Polymorphism,Traits,Trait Objects,我有一个方法,我需要用一个trait参数调用它(让我们称它为Listener)。原因是,有时我以前将此trait参数存储到父结构中,因此它位于框中,有时则不在其中 所以我有两种方法: fref(t:&t)其中t:Listener fbox(t:&Box) 我想让他们两个都调用f(t:?)。现在,我复制了fref和fbox中的代码,这两个代码都可以工作,但效果不好。因此,我正在寻找f的签名,它可以从fref和fbox调用它来分解我的代码。我希望通过Box实现的特性之一将等同于&(或者至少在某个

我有一个方法,我需要用一个trait参数调用它(让我们称它为
Listener
)。原因是,有时我以前将此trait参数存储到父结构中,因此它位于
框中,有时则不在其中

所以我有两种方法:

  • fref(t:&t)其中t:Listener
  • fbox(t:&Box)
我想让他们两个都调用
f(t:?)
。现在,我复制了
fref
fbox
中的代码,这两个代码都可以工作,但效果不好。因此,我正在寻找
f
的签名,它可以从
fref
fbox
调用它来分解我的代码。我希望通过
Box
实现的特性之一将等同于
&
(或者至少在某个地方找到一个共同点)

我尝试了以下方法:

  • 写入
    f(t:&t),其中t:Listener
    ,但是我不能从
    fbox
    调用(
    Listener
    不是由
    Box
    实现的)
  • 然后将调用从
    fbox
    更改为
    f(&*t)
    以取消对我的
    框的装箱
    ,但由于
    t
    不是
    大小
    d,我无法取消装箱

  • 编写
    f(t:&t),其中t:std::borrow::borrow
    但是我不能从
    fref
    调用(
    borrow
    不是由
    侦听器实现的)

  • AsRef相同
  • 上次尝试使用
    Deref
trait侦听器{}
结构鼠标{}
鼠标{}的impl侦听器
fn fbox(t:&盒){
f(t);
}
fn fref(t:&t)
哪里
T:听众,
{
f(t);
}
fn f(t:&t)
哪里
T:std::ops::Deref,
{
}
fn create_listener()->impl listener{
鼠标{}
}
fn main(){
让鼠标=创建_侦听器();
让box_鼠标:box=box::new(鼠标{});
fref(鼠标);
fbox(&box_鼠标);
}

侦听器
是一个特征,因此
Box
实际上是一个特征对象,
Box
-不幸的是,
dyn
关键字当前是可选的。
鼠标
实现
Deref
,与实现
侦听器的
目标
类型关联。在
&鼠标
的情况下,deref
目标
鼠标
,但在
的情况下,它是一个未知对象,
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);
}

&T
Box
都使用
Target=T
执行
Deref
。这就是你想要的吗?这有点不清楚,因为您没有提供。我稍微改进了@Stargateurok的示例。我添加了一个基于@Stargateur的mcve,带有问题命名和DerefIt的尝试,因为
Listener
是一个特性。该框实际上是一个trait对象
box
,而另一个是一个常规类型参数。我不感谢您,因为在其中一个框中,您尝试使用静态分派函数和动态分派数据。但是我可能错过了一些东西我想我终于明白了
的用途了吗?这是不是意味着
f
使用动态调度?或者,由于它是通用的,只有当
f
box
?@Stargateur一起使用时,动态分派才会对装箱的trait对象使用动态分派,但不会对已知类型使用。请记住,
f
将为每个可能的
T
获得单态。
fn fbox(listener: &Box<dyn Listener>) {
    f(listener);
}

fn fref<L>(listener: &L)
where
    L: Listener
{
    f(&listener);
}
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
{
}