Rust Deref 与在内部类型上实现迭代器
Rust Deref vs Implementing Iterators over inner types
这是一个包含向量的玩具结构
struct SizedVec {
items: Vec<u32>,
cap: usize,
}
我想在 SizedVec
上使用迭代函数,这样它们就可以像我直接迭代项目一样工作。
但是,我不确定应该实施哪些特征:Iterator
和 IntoIterator
够吗? the docs 有很多特点
而且它们看起来有点复杂和乏味。
然后我看到我可以实现 Deref
和 DerefMut
并使用 deref 强制免费获得所有这些功能:
果然,这样做之后:
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
}
}
我可以使用所有我想要的迭代器。但是我想实现一个推送的自定义逻辑,但是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);
}
}
}
这似乎有效,
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)
}
这一切似乎都很有效,但我的问题是:这是个好主意吗?如果我将我的 SizedVec
转换为通用类型,我会遇到问题吗?
如果这是个坏主意,有没有一种简单的方法可以将内部向量项的所有 iteration/map 功能放到封闭结构中?
此外,这是否有任何性能方面的考虑?
Deref
很好,因为你的结构特别是一个具有额外不变量的 vec(因此使其可用 as vec 似乎是明智的)但 DerefMut
似乎就像一个相当糟糕的主意,因为它会让调用者泄漏内部 Vec
(作为可变引用)并破坏你的不变量。
一个选项可能是 Deref
到一个切片(而不是 vec),在这种情况下 DerefMut
也会给你一个切片,它有相当严格的限制,因此不会能够打破你的不变量。这将意味着您可能需要重新实现固有的 Vec
方法,并且无法冒充 Vec
。
另一种选择是根本不实现 DerefMut
,并为它们提供更明确的方法。还有 WRT 迭代器,请注意,您只需要实现 IntoIterator
和其他迭代器生成方法(.iter()
、.iter_mut()
):结果可以是底层集合 [=40= 的任何迭代器].
现在我不知道你的意思
However, I was not sure which traits I should implement: are Iterator [...] enough?
在任何情况下,您都不应该直接在您的 SizedVec
上实施 Iterator
。这是一个非常糟糕的想法。
迭代器子特征基本上是标记,它们提供了 Iterator
的附加功能(但不一定由每个 Iterator
类型实现)。如果您正确地委托您的迭代,底层迭代器类型可能已经实现了那些可能的。
这是一个包含向量的玩具结构
struct SizedVec {
items: Vec<u32>,
cap: usize,
}
我想在 SizedVec
上使用迭代函数,这样它们就可以像我直接迭代项目一样工作。
但是,我不确定应该实施哪些特征:Iterator
和 IntoIterator
够吗? the docs 有很多特点
而且它们看起来有点复杂和乏味。
然后我看到我可以实现 Deref
和 DerefMut
并使用 deref 强制免费获得所有这些功能:
果然,这样做之后:
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
}
}
我可以使用所有我想要的迭代器。但是我想实现一个推送的自定义逻辑,但是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);
}
}
}
这似乎有效,
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)
}
这一切似乎都很有效,但我的问题是:这是个好主意吗?如果我将我的 SizedVec
转换为通用类型,我会遇到问题吗?
如果这是个坏主意,有没有一种简单的方法可以将内部向量项的所有 iteration/map 功能放到封闭结构中?
此外,这是否有任何性能方面的考虑?
Deref
很好,因为你的结构特别是一个具有额外不变量的 vec(因此使其可用 as vec 似乎是明智的)但 DerefMut
似乎就像一个相当糟糕的主意,因为它会让调用者泄漏内部 Vec
(作为可变引用)并破坏你的不变量。
一个选项可能是 Deref
到一个切片(而不是 vec),在这种情况下 DerefMut
也会给你一个切片,它有相当严格的限制,因此不会能够打破你的不变量。这将意味着您可能需要重新实现固有的 Vec
方法,并且无法冒充 Vec
。
另一种选择是根本不实现 DerefMut
,并为它们提供更明确的方法。还有 WRT 迭代器,请注意,您只需要实现 IntoIterator
和其他迭代器生成方法(.iter()
、.iter_mut()
):结果可以是底层集合 [=40= 的任何迭代器].
现在我不知道你的意思
However, I was not sure which traits I should implement: are Iterator [...] enough?
在任何情况下,您都不应该直接在您的 SizedVec
上实施 Iterator
。这是一个非常糟糕的想法。
迭代器子特征基本上是标记,它们提供了 Iterator
的附加功能(但不一定由每个 Iterator
类型实现)。如果您正确地委托您的迭代,底层迭代器类型可能已经实现了那些可能的。