Associated Types in Rust are similar to Generic Types; however, Associated Types limit the types of things a user can do, which consequently facilitates code management. Among the Generic Types of traits, types that depend on the type of trait implementation can be expressed by using the Associated Type syntax.
By comparing the Associated and Generic Types, you can get a better understanding of Associated Types.
The Generic Type always has a <> attached, and moves together with it. However, the Associated Type does not specify anything after the type. For instance, if the type returned by the Iterator is Generic, the result would be Iterator<Item>. However, if you were to use the Associated Type, it would simply be Iterator.
Code using the Associated Type can be replaced with code using the Generic Type, but not the other way around. For example, if you want an easy way to convert i32 type variables and i64 type variables to BigInt types, the BigInt type would implement From<i32> and From<i64>. At this point, the FromType of From<FromType> can not be created as an Associated Type since one BigInt type can implement multiple From<FromType>.
By using Associated Types instead of Generic, you can reduce unnecessary code modifications. While writing code with Rust, you may run into a situation where you need to declare a new Generic Type in the middle of everything. In this case, you will need to fix a substantial amount of unrelated code as well. To be more specific, you will need to add Generic Type arguments to all functions from the point of creation of the values that the Generic Type uses, all the way until that value itself is deleted. However, if the type I want to add can be represented as an Associated Type, I can reduce unnecessary code modifications.
For example, let’s say that you’ve created the FromStr trait yourself, which creates an arbitrary type from a String value. An example is shown below, where the from_str function returns Self upon success and String upon failure.
The example above was decent; however, I wanted to express an Error type, which would hold more variety of information than String.
In order to solve this problem, I’ve tried the method as shown above. However, this requires me to fix the entire code. I need to add the Err type in every single instance where FromStr type is used.
The following code does not care about the Err type; however, even this code needs to be fixed!
However, if you use AssociatedTypes, you do not need to modify the code of a function that have no relation to Err such as do_great_work.
CodeChain takes advantage of Associated Types in necessary situations. For example, CacheableItem trait is a trait that must be implemented by the type that will be used in the cache. This trait requires the Address type in order to find the correct value in the cache. You can declare this type as Generic, but it would be more natural to use the Associated Type. The reason is that there will never be an instance where one would use two different Addresses for a type that needs to be cached. You can check out the code discussed just now in the link below.