struct A {}
struct B {}
enum Symbol {
SymbolA(A),
SymbolB(B)
}
and I want to implement a method for structs A and B:
trait say {
fn say(&self);
}
impl say for A {
fn say(&self) {
print!("it's symbol A");
}
}
impl say for B {
fn say(&self) {
print!("it's symbol B");
}
}
but I store values in a Vector of Symbol:
let vec: Vec<Symbol> = Vec::new()
vec.push(Symbol::SymbolA(A{}));
vec.push(Symbol::SymbolB(B{}));
vec[0].say()
compiler says there is no method say in Symbol. So I implemented it:
impl say for Symbol {
fn say(&self) {
print!("Random symbol");
}
}
but then, the output of
vec[0].say()
is Random symbol but not it's symbol A as I expected.
So how do I call the method say of A? Maybe I shouldn't use Vector of Symbol? But then how do I place A and B in the same vector? Well, I could create two vectors, one for A and one for B, but it would be hard to iterate through them in correct order
Well, it is definitely solves issue, thanks, but I feel like I should use rust's Trait. I mean, why then do I need impl TraitName for StructName instead of impl StructName since I either have a variable of the specific struct type so I can call it directly (like this variable.method() ) or I don't know the type of variable, but then can't call it's method (until I use a match, but then I can just call random func, it doesn't have to be implemented in my object)
A trait is only useful if you are going to write generic functions that accept any of your types — that is, functions that will accept not just &Symbol but also an &A or &B that is not wrapped in Symbol. If you are not going to need any such functions, then there is very little advantage to defining a trait.
If you want the enum itself to implement that trait, you can implement it yourself, and then do the match and call the functions in each item. Or, you can let the enum_dispatch crate do all that for you.
And I can unwrap A and B out of Symbol using match, right? But since function accepts both A and B, I don't have to write the function call for every sub-struct of the enum Symbol? Or I do?
Yes, but only in a function that accepts Symbol specifically, not in a generic function using a trait.
I'm not sure what you mean here.
If you want a trait, you have to write the appropriate fn say for every type that implements the trait. Once you have written the trait, generic functions need only call the trait function to handle every type implementing the trait.