我一直在努力寻找关于Rust如何在涉及模块边界的情况下解决特征毯实现的文档,但没有发现太多与之直接相关的内容。
让我们考虑一个具有两个相似但略有不同的代码片段的示例:
第一个代码段编译得很好,但会遇到无限的运行时递归。这是因为T: Iterator+Clone
的ClonableIterator
的一揽子实现与Box<dyn ClonableIterator<'a>>
相匹配,这要归功于我们手动实现的Clone
和Box
的Iterator
的一揽子实现,现在是Iterator+Clone
。
//the trait itself, with the indirection to call box_clone on the base type
trait ClonableIterator<'a>: Iterator<Item = &'a u32> + 'a {
fn box_clone(&self) -> Box<dyn ClonableIterator<'a>>;
}
//The blanket implementation of the trait for all clonable iterators
impl<'a, T: Iterator<Item = &'a u32> + Clone + 'a> ClonableIterator<'a> for T {
fn box_clone(&self) -> Box<dyn ClonableIterator<'a>> {
Box::new(self.clone())
}
}
//Clone for the box. Does not work
impl<'a> Clone for Box<dyn ClonableIterator<'a>> {
fn clone(&self) -> Self {
(*self).box_clone()
}
}
fn main() {
let input = vec![1,2,3,4,5];
let iter1 : Box<dyn ClonableIterator> = Box::new(input.iter());
let iter2 : Box<dyn ClonableIterator> = Box::new(iter1.clone().filter(|&&x| x%2 == 0));
println!("{} {}", iter1.sum::<u32>(), iter2.sum::<u32>())
}
(游乐场(
第二个片段只是对上述内容的一个轻微修改,即Clone
特性的实现已移至子模块。然而,它正在发挥作用,并按照人们的期望行事。ClonableIterator
创建的Trait对象是Clone
和Iterator
,对它们调用clone()
方法会创建装箱迭代器的实际副本Iterator
方法和clone()
都可以直接在Box<dyn ClonableIterator>
上调用,从中创建的迭代器又是Clone+Iterator
,因此可以从中创建ClonableIterator
特征对象。
//the trait itself, with the indirection to call box_clone on the base type
trait ClonableIterator<'a>: Iterator<Item = &'a u32> + 'a {
fn box_clone(&self) -> Box<dyn ClonableIterator<'a>>;
}
//The blanket implementation of the trait for all clonable iterators
impl<'a, T: Iterator<Item = &'a u32> + Clone + 'a> ClonableIterator<'a> for T {
fn box_clone(&self) -> Box<dyn ClonableIterator<'a>> {
Box::new(self.clone())
}
}
//a helper module, to prevent the above blanket implementation from matching
//the Box<dyn super::ClonableIterator<'a>>.
//I can't find the documentation how this works, but it does work.
mod helper {
impl<'a> Clone for Box<dyn super::ClonableIterator<'a>> {
fn clone(&self) -> Self {
(*self).box_clone()
}
}
}
fn main() {
let input = vec![1,2,3,4,5];
let iter1 : Box<dyn ClonableIterator> = Box::new(input.iter());
let iter2 : Box<dyn ClonableIterator> = Box::new(iter1.clone().filter(|&&x| x%2 == 0));
println!("{} {}", iter1.sum::<u32>(), iter2.sum::<u32>())
}
(游乐场(
请有人解释或链接相关文档,说明应用特性一揽子实现的规则与特性本身可用的规则有何不同?
我没有完整引用参考手册的所有部分,但我看到这两种情况之间的区别是ClonableIterator
在mod helper
中不可见(没有use super::ClonableIterator
(。因此,在查找方法时,对于任意类型,不会参考该特性,但(显然(对于dyn super::ClonableIterator
,可能是因为不这样做毫无帮助。
因此,方法查找过程大致如下:
- 我们从
*self
开始,它是Box<dyn CloneableIterator<'a>>
类型的&Box<dyn CloneableIterator<'a>>
的显式解引用。- 这有一个名为
box_clone()
的固有方法吗?没有 - 任何可见特征都有一个名为
box_clone()
的方法吗?- 在第一个程序中,是(
ClonableIterator
在同一范围内声明(,因此调用了一个 - 在第二个程序中,没有,所以继续
- 在第一个程序中,是(
- 这有一个名为
- 对CCD_ 28进行去引用,得到CCD_。
- 这有一个名为
box_clone()
的固有方法吗?没有 - 任何可见特征都有一个名为
box_clone()
的方法吗?是的,显然CloneableIterator
对于dyn
类型是无条件可见的
- 这有一个名为