Reading the Rust book and struggling to understand why I should use traits over methods if I still need to write an implementation of the trait for each object that can have that trait.
Apart from the convenience of being able to have the same generic names for functions in a trait for multiple objects (e.g. structs A, B and C can all have the same trait implementation name .save()), I still have to write as much if not more code for all implementations over just writing a method for each struct.
-
2Ever hear that you should program to interfaces rather than concrete implementations? Also, traits can have default implementations. You use a trait when you want to decouple a behavior (verb) from a specific struct (noun). Glancing at your profile it looks like you're a Python programmer. This idea is not as big a deal in dynamically typed languages: there you'd probably use some sort of mixin pattern instead.Jared Smith– Jared Smith2025-03-25 13:03:56 +00:00Commented Mar 25 at 13:03
Add a comment
|
1 Answer
Polymorphism
Rust's trait is somewhat equivalent's to Go or Java's interface : it describes an interface, separately from any implementation.
From there, you can write functions which operate on the interface regardless of the type which actually implements the trait. For example:
fn sum<I>(sequence: I) -> i64
where
I: IntoIterator<Item = i64>
{
let mut result = 0;
for i in sequence {
result += i;
}
result
}
Therefore, the shared behavior isn't in the trait, it's in the users of the trait: the behavior implemented in the structs and functions which operate on the trait (via generics or dyn traits), regardless of the actual implementor.
4 Comments
Heiko
This example works great because you give
sequence the IntoIterator trait, but as far as I understand, somebody (the Rust devs in this case) still had to write separate implementations for each type that can have that trait e.g. vectors, linked lists, hashmaps... If that is correct, is there any use for this unless my traits depend on other already written traits?Matthieu M.
@Heiko: Do note that
sum here isn't part of a trait. That is, your misunderstanding is that the sharing doesn't occur in the trait, but instead occurs in code which uses the trait. From a trait user perspective, I get to write code once, no matter how many types implement the trait.Heiko
I think I understand it now. To see the utility of traits, one must look from the trait user perspective. In combination with Jared Smith's comment I found this helpful and will mark this as accepted.
Matthieu M.
@Heiko: I went and read the Rust Book's page on traits, and I admit that I feel the led is somewhat buried there. Unfortunately, I'm not sure how to improve it, as presenting a generic function upfront seems kinda... brutal. I guess it's one of those things where users familiar with interfaces/traits/type-classes will feel at home immediately, but for a beginner or a user of dynamic languages, it's really not obvious that you need to read so far to finally understand where it's leading... if you have suggestions on how to improve this page, I'm sure they'd be welcome.