4

首先,我知道Box如果我想定义一个递归结构,我可以使用。例如,

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
    }
}

但是如何通过模板或特征对象在这些结构上创建特征?由于 的存在fn append_next(...) -> Self,我不能像这样直接创建特征对象:

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

而且我们不能退货Option<Box<impl Linkable>>impl Linkable换货fn get_next(&self)

然后我通过通用模板尝试了以下实现,但它不起作用。因为我需要T在构造一个新的LinkNode.

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

我最终以这种方式实现它,通过创建其他特征来提供帮助。而且效果很好。再次......还有其他更好的方法吗?

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()
    }
}

顺便说一句,在上面的探索过程中我还有一些其他问题:为什么 Rust 禁止impl Linkable糖,比如Box<impl Linkale>? 为什么impl Linkable在一个特征中禁止返回?


在Ibraheem的回答之后更新:

除了来自Ibraheem的关联类型实现之外,像这样工作也很好。核心思想是避免 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,
}

这在另一个问题中提到:我可以在 Rust 中定义一个带有自身类型参数的特征吗?

4

1 回答 1

1

Linkable可能有关联类型称为Next.

pub trait Linkable {
    type Next: Linkable;
}

get_next现在返回 type的实例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;
}

现在您可以Linkable实现Linknode

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

为什么 Rust 禁止 impl Linkable 糖,比如 Box?以及为什么在特征中禁止返回 impl Linkable ?

您可以参考Is it possible to use impl Traitas a function's return type in a trait definition? 对于这个问题的答案。

于 2021-01-22T16:14:03.700 回答