这是一个包含向量的玩具结构
struct SizedVec {
items: Vec<u32>,
cap: usize,
}
Run Code Online (Sandbox Code Playgroud)
我想拥有迭代函数,SizedVec这样它们就可以像我直接迭代项目一样工作。
但是,我不知道我应该实现哪些性状:是Iterator和IntoIterator就够了吗?文档中有很多特征
,它们看起来有点复杂和乏味。
然后我看到我可以使用 deref coercion 免费实现Deref和DerefMut获取所有这些功能:
果然,做完之后:
impl Deref for SizedVec {
type Target = Vec<u32>;
fn deref(&self) -> &Self::Target {
&self.items
}
}
impl DerefMut for SizedVec {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.items
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用我想要的所有迭代器。但是我想实现一个自定义的推送逻辑,但是DeRef已经给了我一个推送。但是根据文档我应该没问题,因为显然查找是按顺序为每种类型完成的
impl SizedVec {
fn from_size(size: usize) -> Self {
Self {
items: vec![],
cap: size,
}
}
fn push(&mut self, item: u32) {
if self.items.len() < self.cap {
self.items.push(item);
}else {
self.items.pop();
self.items.push(item);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎有效,
fn main () {
let mut svec = SizedVec::from_size(2); // Custom function I implemented
svec.push(2);
svec.push(3);
svec.push(4);
svec.iter_mut().for_each(|item| {*item = *item + 2});
println!("{}", svec); // Items: [4, 6], Cap: 2 (Implemented Display so this works)
}
Run Code Online (Sandbox Code Playgroud)
这一切似乎都很有效,但我的问题是:这是个好主意吗?如果我将我的转换SizedVec为泛型类型,我会遇到问题吗?
如果这是一个坏主意,是否有一种简单的方法可以将内部向量项的所有迭代/映射功能放到封闭结构上?
另外,是否有任何性能方面的考虑?
Deref是罚款,因为你的结构是专门用另外的不变量(如此使得它可用A VEC为A VEC似乎是合理的),但DerefMut似乎是一个相当糟糕的主意,因为这将让来电者泄露内部Vec(如一个可变的参考),打破你的不变量。
一种选择可能是Deref切片(而不是 vec),在这种情况下,DerefMut也会为您提供一个切片,该切片具有非常严格的限制,因此将无法打破您的不变量。这意味着您可能需要重新实现固有的Vec方法,并且无法将其作为Vec.
另一种选择是根本不实现DerefMut,并为这些提供更明确的方法。还有 WRT 可迭代对象,请注意,您只需要实现IntoIterator和其他迭代器生成方法 ( .iter(), .iter_mut()):结果可以是底层集合返回的任何迭代器。
现在我不知道你的意思
但是,我不确定我应该实现哪些特征:Iterator [...] 足够了吗?
在任何情况下,您都不应该Iterator直接在您的SizedVec. 这是一个可怕的、可怕的想法。
迭代器子特征基本上是标记,它们提供额外的功能Iterator(但不一定由每种Iterator类型实现)。如果您正确委派您的迭代,则底层迭代器类型可能已经实现了那些可能的。