我正在try 在具有相同特征的盒装特征对象上实现特征.我以前做过这样的特征,它的方法是&self,这很好用,但不是self.

// The purpose of this trait is to allow for converting any kind of "group" which might eg be nested tuples like below, and convert it into a flat Vec of Items
trait Group {
    fn into_vec(self) -> Vec<Box<dyn Item>>;
}

trait Item: Group {}

// Foo is an Item an can also be made into a group
struct Foo {}
impl Item for Foo {}
impl Group for Foo {
    fn into_vec(self) -> Vec<Box<dyn Item>> {
        vec![Box::new(self)]
    }
}

// impl Group for data structures which contain items or other nested structures containing items
impl<A: Group, B: Group> Group for (A, B) {
    fn into_vec(self) -> Vec<Box<dyn Item>> {
        let mut new_vec = Vec::new();
        new_vec.extend(self.0.into_vec().into_iter());
        new_vec.extend(self.1.into_vec().into_iter());
        new_vec
    }
}

// Can create a single group fine
fn get_group() -> impl Group {
    (Foo {}, (Foo {}, Foo {}))
}

// Sometimes I might want to return different groups from different braches so need to box them
// However I'm not sure how to implement this. self.into_vec() is an ifinite recursion, and can't deref self either.
impl Group for Box<dyn Group> {
    fn into_vec(self) -> Vec<Box<dyn Item>> {
        (*self).into_vec()
    }
}
fn get_group_conditonal(condition: bool) -> impl Group {
    if condition {
        Box::new((Foo {}, (Foo {}, Foo {}))) as Box<dyn Group>
    } else {
        Box::new(Foo {}) as Box<dyn Group>
    }
}

我意识到,在这个特定的示例中,我可以将fn get_*()个函数更改为返回Box<dyn Group>来解决问题.然而,API的其余部分具有将输入作为impl Group的函数.如果我不能impl Group for Box<dyn Group>,那么这将进入API的其余部分,并要求所有函数只接受盒装特征对象作为输入,而不是impl Group,如果可能的话,我想避免这种情况.

推荐答案

我能想到的唯一解决方案是commonly recommended,那就是让特征方法接受Box<Self>而不是Self:

trait Group {
    fn into_vec(self: Box<Self>) -> Vec<Box<dyn Item>>;
}

然后

impl Group for Box<dyn Group> {
    fn into_vec(self: Box<Self>) -> Vec<Box<dyn Item>> {
        (*self).into_vec()
    }
}

就像你在Playground上看到的那样工作,因为它不必处理原始的dyn Group

Rust相关问答推荐

在本例中,为什么我不能一次多次borrow 可变变量?

AXUM一路由多个不包括URL的参数类型

如何防止Cargo 单据和Cargo 出口发布( crate )项目

使用Rust WASM读取文件

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

.to_owned()、.clone() 和取消引用 (*) 之间有区别吗?

Option<&T> 如何实现复制

返回迭代器的特征

使用 `clap` 在 Rust CLI 工具中设置布尔标志

是否可以在 Rust 中的特定字符上实现特征?

为什么1..=100返回一个范围而不是一个整数?

如何在 Rust 中编写修改 struct 的函数

为什么 Rust 编译器在移动不可变值时执行复制?

用逗号分隔字符串,但在标记中使用逗号

通用函数中的生命周期扣除和borrow (通用测试需要)

在空表达式语句中移动的值

`if let` 只是另一种编写其他 `if` 语句的方式吗?

如何构建包含本地依赖项的 docker 镜像?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?

为什么 Rust 中的关联类型需要明确的生命周期注释?