pub struct Kitty<Hash, Balance> {
id: Hash,
dna: Hash,
price: Balance,
gender: Gender,
}
Here, the struct takes two type parameters, Hash
and Balance
. You could have a Kitty<String, u32>
for example, in which id
and dna
would be String
s and price
would be a u32
. gender
, in contrast, is always a field with type Gender
.
impl<T: Config> Kitty<T, T> { /* ... */ }
They say Kitty<T, T>
here because they needed to specify both type parameters and make sure they were the same. (If they always had to be the same, Kitty
would only have one type parameter.)
Also, T: Config
is saying "use this implementation for any type T
that implements Config
". Config
is a trait. Because of this trait bound, they can make use of the Config
trait properties on T
inside the implementation. For example here:
pub fn gender(dna: T::Hash) -> Gender { /* ... */ }
We can see that the Config
type must have an associated type called Hash
. (Note that, just like function parameters names need not be related to the variables you call them with, this associated type need not be related to the type parameter on Kitty
.)
If they didn't have the bound, they wouldn't be able to use T::Hash
, or any other properties of the Config
trait; the bound is checked at compile time.
P.s. Welcome to URLO! Please see the pinned formatting post. 