1. Introduction
Traits is a concept in Rust, similar to interfaces in other programming languages, although with a number of differences.
Each data type will have a number of methods defined and only variables of that data type can be called. If we want to share a method that many types can share, customizing each type, we will need to use traits .
Here we have two structs NewArticle
and Tweet
with different data fields, both of which need a summarize
method to summarize the data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> headline <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> location <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> author <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> reply <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> retweet <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> |
1 2 3 4 | <span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
We define traits with the trait
keyword, followed by Summary
(the trait’s name). The summarize
function returns the type String
. Like functions in interfaces in some other languages, functions in traits end with a ;
and no function body. Because it is just a prototype for other data types to implement.
2. Implement Trait
Implement trait with data type
Now it’s time to implement summarize
method on 2 struct NewsArticle
and Tweet
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <span class="token comment">// src/lib.rs</span> <span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> headline <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> location <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> author <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token comment">// trả về chuỗi gồm 3 thông tin: headline, author và localtion</span> <span class="token macro property">format!</span> <span class="token punctuation">(</span> <span class="token string">"{}, by {} ({})"</span> <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> headline <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> author <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> location <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> reply <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> retweet <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token comment">// trả về chuỗi gồm 2 thông tin: username và content</span> <span class="token macro property">format!</span> <span class="token punctuation">(</span> <span class="token string">"{}: {}"</span> <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> username <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> content <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Implementing a trait for a data type is similar to implementing a regular method for that data type. The only difference is that after the impl
keyword will be the name of the trait you want to use and then the for
keyword.
Now that the library has implemented the NewsArticle and Tweet Summary trait, users of the bucket can call the trait methods on NewsArticle and Tweet instances in the same way we call regular methods. The only difference is that the user has to include the trait in the scope as well as the types. Here is an example of how binaries can use our composite library:
We have just implemented the Summary trait implementation for two types NewsArticle
and Tweet
. Now, we can call the summarize
method from NewsArticle
or Tweet
instances like normal methods. Of course, depending on whether the instance is of type NewsArticle
or Tweet
, the corresponding summarize
function will be executed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">use</span> <span class="token namespace">aggregator <span class="token punctuation">::</span></span> <span class="token punctuation">{</span> <span class="token class-name">Summary</span> <span class="token punctuation">,</span> <span class="token class-name">Tweet</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> tweet <span class="token operator">=</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"horse_ebooks"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"of course, as you probably already know, people"</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> reply <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> retweet <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token macro property">println!</span> <span class="token punctuation">(</span> <span class="token string">"1 new tweet: {}"</span> <span class="token punctuation">,</span> tweet <span class="token punctuation">.</span> <span class="token function">summarize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 1 new tweet: horse_books: of course, as you probably already know, people</span> <span class="token punctuation">}</span> |
Default Implementations
Sometimes it is useful to have default behavior for some or all of the methods in a trait rather than requiring implementations for all methods on every type. Then when we implement the trait on a particular type, we can keep or override the default behavior of each method.
Sometimes we will need a generic default method with types instead of having to implement methods on each of the different types. Then, if we want to change depending on the data type, we can choose the override option.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"(Read more...)"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> headline <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> location <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> author <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token comment">// Sử dụng phương thức summarize mặc định của trait Summary</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> reply <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> retweet <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token comment">// Ghi đè phương thức summarize mặc định</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token macro property">format!</span> <span class="token punctuation">(</span> <span class="token string">"{}: {}"</span> <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> username <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> content <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">use</span> <span class="token namespace">aggregator <span class="token punctuation">::</span></span> <span class="token punctuation">{</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">,</span> <span class="token class-name">Summary</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> article <span class="token operator">=</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span> headline <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Penguins win the Stanley Cup Championship!"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> location <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Pittsburgh, PA, USA"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> author <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Iceburgh"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"The Pittsburgh Penguins once again are the best hockey team in the NHL."</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token macro property">println!</span> <span class="token punctuation">(</span> <span class="token string">"New article available! {}"</span> <span class="token punctuation">,</span> article <span class="token punctuation">.</span> <span class="token function">summarize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// New article available! (Read more...)</span> <span class="token punctuation">}</span> |
The default method can call other methods with the same trait , even if the method is only in prototype form. This feature will provide many useful things, let’s take a look at the example below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">;</span> <span class="token comment">// phương thức summarize gọi phương thức summarize_author để in ra kết quả</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token macro property">format!</span> <span class="token punctuation">(</span> <span class="token string">"(Read more from {}...)"</span> <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> <span class="token function">summarize_author</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token keyword">pub</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> reply <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token keyword">pub</span> retweet <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> <span class="token comment">// Triển khai phương thức summarize_author in ra @ + tên tác giả</span> <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token keyword">self</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span> <span class="token macro property">format!</span> <span class="token punctuation">(</span> <span class="token string">"@{}"</span> <span class="token punctuation">,</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> username <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">use</span> <span class="token namespace">aggregator <span class="token punctuation">::</span></span> <span class="token punctuation">{</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> <span class="token class-name">Summary</span> <span class="token punctuation">,</span> <span class="token class-name">Tweet</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">fn</span> <span class="token function-definition function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> tweet <span class="token operator">=</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"horse_ebooks"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"of course, as you probably already know, people"</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> reply <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> retweet <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token macro property">println!</span> <span class="token punctuation">(</span> <span class="token string">"1 new tweet: {}"</span> <span class="token punctuation">,</span> tweet <span class="token punctuation">.</span> <span class="token function">summarize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// 1 new tweet: (Read more from @horse_ebooks...)</span> <span class="token punctuation">}</span> |
Instead of returning a fixed string like in the previous example, the summarize
method by calling summarize_author
customizes the Tweet’s author name in the returned results.
Trait as parameter
We already know how to define and implement trait above. In addition, trait can also act as a parameter in a function when defined with the impl
keyword as follows:
1 2 3 4 | <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span> <span class="token punctuation">(</span> <span class="token string">"Breaking news! {}"</span> <span class="token punctuation">,</span> item <span class="token punctuation">.</span> <span class="token function">summarize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Instead of defining the struct data type to be passed to NewArticle
or Tweet
, for example, we will replace it with &impl
. The input parameter of the function will then receive all data types that implement trait Summary. If passing a data type that does not implement trait , the compiler will report an error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | pub trait Summary { fn summarize(&self) -> String; } pub struct NewsArticle { pub headline: String, pub location: String, pub author: String, pub content: String, } impl Summary for NewsArticle { fn summarize(&self) -> String { format!("{}, by {} ({})", self.headline, self.author, self.location) } } pub struct Tweet { pub username: String, pub content: String, pub reply: bool, pub retweet: bool, } impl Summary for Tweet { fn summarize(&self) -> String { format!("{}: {}", self.username, self.content) } } pub fn notify(item: &impl Summary) { println!("Breaking news! {}", item.summarize()); } fn main() { let tweet = Tweet { username: String::from("Pool and Billiards for Dummies"), content: String::from( "Billards Pool", ), reply: false, retweet: false, }; let article = NewsArticle { headline: String::from("Penguins win the Stanley Cup Championship!"), location: String::from("Pittsburgh, PA, USA"), author: String::from("Iceburgh"), content: String::from( "The Pittsburgh Penguins once again are the best hockey team in the NHL.", ), }; notify(&tweet); // Breaking news! Pool and Billiards for Dummies: Billards Pool notify(&article); // Breaking news! Penguins win the Stanley Cup Championship!, by Iceburgh (Pittsburgh, PA, USA) } |
Trait Bound Syntax
On how to define trait as a function parameter as above, we can use the generic syntax as follows:
1 2 3 4 | <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token operator"><</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">></span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token macro property">println!</span> <span class="token punctuation">(</span> <span class="token string">"Breaking news! {}"</span> <span class="token punctuation">,</span> item <span class="token punctuation">.</span> <span class="token function">summarize</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
In case the function has many trait parameters, these will look like code that looks much more concise
1 2 3 4 5 6 7 8 | <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token punctuation">(</span> item1 <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">,</span> item2 <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token operator"><</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">></span> <span class="token punctuation">(</span> item1 <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">,</span> item2 <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
<T: Summary>
implies that T only accepts data types for the implementation trait Summary
Use the + . operator
What if you want the input parameter to be a data type that implements multiple trait at the same time? We will use the math +
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token punctuation">(</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token comment">// hoặc</span> <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span> <span class="token operator"><</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span> <span class="token operator">></span> <span class="token punctuation">(</span> item <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Input data type requires to implement both trait
Use where . keyword
When defining multiple generic data types plus each type needs to implement many trait , the definition syntax using + sign is somewhat cumbersome when suddenly extending the function definition line.
1 2 | <span class="token keyword">fn</span> <span class="token function-definition function">some_function</span> <span class="token operator"><</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token class-name">Display</span> <span class="token operator">+</span> <span class="token class-name">Clone</span> <span class="token punctuation">,</span> <span class="token class-name">U</span> <span class="token punctuation">:</span> <span class="token class-name">Clone</span> <span class="token operator">+</span> <span class="token class-name">Debug</span> <span class="token operator">></span> <span class="token punctuation">(</span> t <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">,</span> u <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">U</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">i32</span> <span class="token punctuation">{</span> |
Instead, we can use the where keyword, the definition of the necessary trait will be brought down to the second line, making the code look neater and cleaner than in the above example.
1 2 3 4 5 | <span class="token keyword">fn</span> <span class="token function-definition function">some_function</span> <span class="token operator"><</span> <span class="token class-name">T</span> <span class="token punctuation">,</span> <span class="token class-name">U</span> <span class="token operator">></span> <span class="token punctuation">(</span> t <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">T</span> <span class="token punctuation">,</span> u <span class="token punctuation">:</span> <span class="token operator">&</span> <span class="token class-name">U</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">i32</span> <span class="token keyword">where</span> <span class="token class-name">T</span> <span class="token punctuation">:</span> <span class="token class-name">Display</span> <span class="token operator">+</span> <span class="token class-name">Clone</span> <span class="token punctuation">,</span> <span class="token class-name">U</span> <span class="token punctuation">:</span> <span class="token class-name">Clone</span> <span class="token operator">+</span> <span class="token class-name">Debug</span> <span class="token punctuation">{</span> |
3. Return type trait
Trait can be defined as return type in a function, let’s see the example below.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">fn</span> <span class="token function-definition function">returns_summarizable</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"horse_ebooks"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"of course, as you probably already know, people"</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> reply <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> retweet <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Of course the return data type needs to implement trait Summary
However, you can only use Impl Trait if you are returning a single type. The example below returns NewsArticle
or Tweet
will give an error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <span class="token keyword">fn</span> <span class="token function-definition function">returns_summarizable</span> <span class="token punctuation">(</span> switch <span class="token punctuation">:</span> <span class="token keyword">bool</span> <span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> switch <span class="token punctuation">{</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span> headline <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Penguins win the Stanley Cup Championship!"</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> location <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Pittsburgh, PA, USA"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> author <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"Iceburgh"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"The Pittsburgh Penguins once again are the best hockey team in the NHL."</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span> username <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"horse_ebooks"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> content <span class="token punctuation">:</span> <span class="token class-name">String</span> <span class="token punctuation">::</span> <span class="token function">from</span> <span class="token punctuation">(</span> <span class="token string">"of course, as you probably already know, people"</span> <span class="token punctuation">,</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> reply <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> retweet <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |