To implement an iterator in Rust, we only need to implement the next
method, as explained in the documentation. However, the Iterator
trait has many more methods.
As far as I know, we need to implement all the methods of a trait. For instance, this does not compile (playground link):
struct SomeStruct {}
trait SomeTrait {
fn foo(&self);
fn bar(&self);
}
impl SomeTrait for SomeStruct {
fn foo(&self) {
unimplemented!()
}
}
fn main() {}
The error is pretty clear:
error[E0046]: not all trait items implemented, missing: `bar`
--> src/main.rs:8:1
|
5 | fn bar(&self);
| -------------- `bar` from trait
...
8 | impl SomeTrait for SomeStruct {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation
Because every method on Iterator
except next
has a default implementation. These are methods implemented in the trait itself, and implementors of the trait gain them "for free":
struct SomeStruct {}
trait SomeTrait {
fn foo(&self);
fn bar(&self) {
println!("default")
}
}
impl SomeTrait for SomeStruct {
fn foo(&self) {
unimplemented!()
}
}
fn main() {}
You can tell if a trait method has a default implementation or not through the documentation:
Required methods
fn next(&mut self) -> Option<Self::Item>
Provided methods
fn size_hint(&self) -> (usize, Option<usize>)
Note that size_hint
is in the "provided methods" section — that's the indication that there's a default implementation.
If you can implement the method in a more efficient way, you are welcome to do so, but note that it is not possible to call the default implementation if you decide to override it.
Specifically for Iterator
, it's a great idea to implement size_hint
if you can, as that can help optimize methods like collect
.