我一直在尋找有關 Rust 如何在涉及模塊邊界的情況下解決特征毯實作的檔案,但沒有找到與之直接相關的內容。
讓我們考慮一個包含兩個相似但略有不同的代碼片段的示例:
第一個是編譯良好但遭受無限運行時遞回的代碼。發生這種情況是因為ClonableIteratorfor 的全面實施T: Iterator Clone與Box<dyn ClonableIterator<'a>>which is匹配,這要歸功于我們手動實施CloneandBox的全面實施Iteratornow 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>())
}
(游樂場)
第二個片段只是對上面的一個小修改,即將Clonetrait的實作移到一個子模塊中。但是,它正在運行并按照人們的預期作業。創建的 Trait 物件ClonableIterator既是,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>())
}
(游樂場)
有人可以解釋或鏈接相關檔案,說明應用特征全面實作的規則與使特征本身可用的規則有何不同?
uj5u.com熱心網友回復:
我沒有完整參考此處所有部分的參考手冊,但是我在這兩種情況之間看到的區別在(沒有)中ClonableIterator是不可見的 。因此,在查找方法時不會為任意型別查詢 trait ,但(顯然)它是 for ,大概是因為不這樣做會毫無幫助。mod helperuse super::ClonableIteratordyn super::ClonableIterator
因此,方法查找程序將大致執行以下操作:
- 我們從型別
*self的顯式取消參考開始。&Box<dyn CloneableIterator<'a>>Box<dyn CloneableIterator<'a>>- 這是否有一個名為 的固有方法
box_clone()?不。 - 是否有任何可見的 trait 有一個名為 的方法
box_clone()?- 在第一個程式中,是(
ClonableIterator在同一范圍內宣告),因此呼叫了一個。 - 在第二個程式中,沒有,所以繼續。
- 在第一個程式中,是(
- 這是否有一個名為 的固有方法
- 取消參考
Box<dyn CloneableIterator<'a>>以獲取dyn CloneableIterator<'a>.- 這是否有一個名為 的固有方法
box_clone()?不。 - 是否有任何可見的 trait 有一個名為 的方法
box_clone()?是的,顯然CloneableIterator該dyn型別無條件可見。
- 這是否有一個名為 的固有方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/375639.html
