@@ -81,6 +81,11 @@ impl Add<u32> for u32 {
81
81
type Output = u32 ;
82
82
83
83
fn add (self , rhs : u32 ) -> u32 {
84
+ // ^^^
85
+ // This could be written as `Self::Output` instead.
86
+ // The compiler doesn't care, as long as the type you
87
+ // specify here matches the type you assigned to `Output`
88
+ // right above.
84
89
// [...]
85
90
}
86
91
}
@@ -104,8 +109,31 @@ because `u32` implements `Add<&u32>` _as well as_ `Add<u32>`.
104
109
105
110
### ` Output `
106
111
107
- ` Output ` , on the other hand, ** must** be uniquely determined once the types of the operands
108
- are known. That's why it's an associated type instead of a second generic parameter.
112
+ ` Output ` represents the type of the result of the addition.
113
+
114
+ Why do we need ` Output ` in the first place? Can't we just use ` Self ` as output, the type implementing ` Add ` ?
115
+ We could, but it would limit the flexibility of the trait. In the standard library, for example, you'll find
116
+ this implementation:
117
+
118
+ ``` rust
119
+ impl Add <& u32 > for & u32 {
120
+ type Output = u32 ;
121
+
122
+ fn add (self , rhs : & u32 ) -> u32 {
123
+ // [...]
124
+ }
125
+ }
126
+ ```
127
+
128
+ The type they're implementing the trait for is ` &u32 ` , but the result of the addition is ` u32 ` .
129
+ It would be impossible[ ^ flexible ] to provide this implementation if ` add ` had to return ` Self ` , i.e. ` &u32 ` in this case.
130
+ ` Output ` lets ` std ` decouple the implementor from the return type, thus supporting this case.
131
+
132
+ On the other hand, ` Output ` can't be a generic parameter. The output type of the operation ** must** be uniquely determined
133
+ once the types of the operands are known. That's why it's an associated type: for a given combination of implementor
134
+ and generic parameters, there is only one ` Output ` type.
135
+
136
+ ## Conclusion
109
137
110
138
To recap:
111
139
@@ -116,3 +144,8 @@ To recap:
116
144
## References
117
145
118
146
- The exercise for this section is located in ` exercises/04_traits/10_assoc_vs_generic `
147
+
148
+ [ ^ flexible ] : Flexibility is rarely free: the trait definition is more complex due to ` Output ` , and implementors have to reason about
149
+ what they want to return. The trade-off is only justified if that flexibility is actually needed. Keep that in mind
150
+ when designing your own traits.
151
+
0 commit comments