问题描述
首先,我知道如果我想定义递归结构,我可以使用 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
的存在,我无法像这样直接创建 trait 对象:
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,}
这在另一个question: Can I define a trait with a type parameter of itself in Rust?
解决方法
Linkable
可以具有名为 Next
的关联类型。
pub trait Linkable {
type Next: Linkable;
}
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;
}
现在您可以为 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 Trait
as a function's return type in a trait definition? 以获得此问题的答案。