简体   繁体   English

如何在 Rust 中定义递归特征绑定?

[英]How to define a recursive trait bound in Rust?

First, I know I can use Box if I want to define a recursive structure.首先,我知道如果我想定义一个递归结构,我可以使用Box For example,例如,

struct LinkNode {
    next: Option<Box<LinkNode>>
}

impl LinkNode{
    fn get_next(&self) -> Option<Box<LinkNode>>{
        None
    }
    fn append_next(&mut self, next: LinkNode) -> Self{
        self
    }
}

But how can I make a trait on these structures via templates or trait object ?但是如何通过模板或特征 object 在这些结构上制作特征 Due to the existence of fn append_next(...) -> Self , I cannot create a trait object directly like this:由于fn append_next(...) -> Self的存在,我无法像这样直接创建特征 object :

pub trait Linkable {
    fn get_next(&self) -> Option<Box<dyn Linkable>>; 
    fn append_next(&mut self, next: impl Linkable) -> Self;
}

And we cannot return Option<Box<impl Linkable>> or impl Linkable for fn get_next(&self) .我们不能为fn get_next(&self)返回Option<Box<impl Linkable>>impl Linkable Linkable 。

Then I tried the following implementation via generic templates and it does not work.然后我通过通用模板尝试了以下实现,但它不起作用。 Because I need to assign the type of T recursively when construct a new LinkNode .因为我需要在构造新的LinkNode时递归地分配T的类型。

pub trait Linkable<T:Linkable<T> + Clone> : Clone {
    fn get_next(&self) -> Option<Box<T>>;
    fn append_next(&mut self, next: T) -> Self;
}

I finally implement it in this way, by creating other traits for assistance.我最终以这种方式实现它,通过创建其他特征来提供帮助。 And it works well.而且效果很好。 Again...Is there other better ways?再次......还有其他更好的方法吗?

pub trait Linkable: LinkClone{
    fn get_next(&self) -> Option<Box<dyn Linkable>>;
}

pub trait LinkAppend {
    fn append_next(&mut self, next: Box<dyn Linkable>) -> Box<dyn Linkable>;
}
pub trait LinkClone{
    fn clone_box(&self) -> Box<dyn Linkable>;
}

impl<T> LinkClonefor T
where
    T: 'static + Linkable+ LinkAppend + Clone,
{
    fn clone_box(&self) -> Box<dyn Linkable> {
        Box::new(self.clone())
    }
}

impl Clone for Box<dyn Linkable> {
    fn clone(&self) -> Box<dyn Linkable> {
        self.clone_box()
    }
}

BTW, I have some other questions during the exploration above: Why Rust forbids the impl Linkable sugar, like the Box<impl Linkale> ?顺便说一句,我在上面的探索过程中还有一些其他问题:为什么 Rust 禁止impl Linkable Linkable 糖,如Box<impl Linkale> And why returning impl Linkable is forbidden in a trait?以及为什么在特征中禁止返回impl Linkable


Updated after Ibraheem 's answer:Ibraheem的回答之后更新

Except the associated type implementation from Ibraheem , it is also fine to work like this.除了来自Ibraheem的关联类型实现之外,像这样工作也很好。 The core idea is to avoid the recursive type declaration in the trait.核心思想是避免 trait 中的递归类型声明。

pub trait Linkable {
    fn get_next<T:Linkable>(&self) -> Next<T>; 
    fn append_next<T:Linkable>(&mut self, next: Next<T>) -> Self;
}

struct Next<T: Linkable> {
    node: T,
}

This is mentioned in another question: Can I define a trait with a type parameter of itself in Rust?这在另一个问题中提到:我可以在 Rust 中定义一个带有自身类型参数的特征吗?

Linkable could have associated type called Next . Linkable可能具有名为Next的关联类型。

pub trait Linkable {
    type Next: Linkable;
}

get_next now returns an instance of type Self::Next , and append_next takes Self::Next as a parameter: get_next现在返回一个Self::Next类型的实例,并且append_nextSelf::Next作为参数:

pub trait Linkable {
    type Next: Linkable;
    
    fn get_next(&self) -> Option<Self::Next>;
    fn append_next(&mut self, next: Self::Next) -> &Self;
}

Now you can implement Linkable for Linknode :现在您可以为Linknode Linkable

impl Linkable for LinkNode {
    type Next = LinkNode;
    
    fn get_next(&self) -> Option<Box<LinkNode>> { 
        None
    }
    fn append_next(&mut self, next: LinkNode) -> &Self {
        self
    }
}

Why Rust forbids the impl Linkable sugar, like the Box?为什么 Rust 禁止 impl Linkable 糖,如 Box? And why returning impl Linkable is forbidden in a trait?以及为什么在特征中禁止返回 impl Linkable ?

You can refer to Is it possible to use impl Trait as a function's return type in a trait definition?您可以参考Is it possible to use impl Trait as a function's return type in a trait definition? for the answer to this question.对于这个问题的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM