Rust 因子分解法;盒子<;T>;及;T作为论据
我有一个方法,我需要用一个trait参数调用它(让我们称它为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实现的特性之一将等同于&(或者至少在某个
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
{
}