[英]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_next
将Self::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.