<buttonid="sidebar-toggle"class="icon-button"type="button"title="Toggle Table of Contents"aria-label="Toggle Table of Contents"aria-controls="sidebar">
<ahref="print.html"title="Print this book"aria-label="Print this book">
<iid="print-button"class="fa fa-print"></i>
</a>
</div>
</div>
<divid="search-wrapper"class="hidden">
<formid="searchbar-outer"class="searchbar-outer">
<inputtype="search"name="search"id="searchbar"name="searchbar"placeholder="Search this book ..."aria-controls="searchresults-outer"aria-describedby="searchresults-header">
<p>We have seen traits before: <code>Debug</code>, <code>Copy</code>, <code>Clone</code> are all traits. To give a type a trait, you have to implement it. Because <code>Debug</code> and the others are so common, we have attributes that automatically do it. That's what happens when you write <code>#[derive(Debug)]</code>: you are automatically implementing <code>Debug</code>.</p>
<p>But other traits are more difficult, so you need to implement them manually with <code>impl</code>. For example, <code>Add</code> (found at <code>std::ops::Add</code>) is used to add two things. But Rust doesn't know exactly how you want to add things, so you have to tell it.</p>
<p>We can add <code>first_thing</code> and <code>second_thing</code>, but we need to give more information. Maybe we want an <code>f32</code>, so something like this:</p>
let result = self.second_thing as u32 + self.first_thing
<spanclass="boring">}
</span></code></pre></pre>
<p>Or maybe we want to just put <code>self.first_thing</code> next to <code>self.second_thing</code> and say that this is how we want to add. So if we add 55 to 33.4, we want to see 5533.4, not 88.4.</p>
<p>So first let's look at how to make a trait. The important thing to remember about <code>trait</code>s is that they are about behaviour. To make a trait, write <code>trait</code> and then create some functions.</p>
<pre><preclass="playground"><codeclass="language-rust">struct Animal { // A simple struct - an Animal only has a name
name: String,
}
trait Dog { // The dog trait gives some functionality
fn bark(&self) { // It can bark
println!("Woof woof!");
}
fn run(&self) { // and it can run
println!("The dog is running!");
}
}
impl Dog for Animal {} // Now Animal has the trait Dog
fn main() {
let rover = Animal {
name: "Rover".to_string(),
};
rover.bark(); // Now Animal can use bark()
rover.run(); // and it can use run()
}
</code></pre></pre>
<p>This is okay, but we don't want to print "The dog is running". You can change the methods that a <code>trait</code> gives you if you want, but you have to have the same signature. That means that it needs to take the same things, and return the same things. For example, we can change the method <code>.run()</code>, but we have to follow the signature. The signature says:</p>
<pre><preclass="playground"><codeclass="language-rust">struct Animal { // A simple struct - an Animal only has a name
name: String,
}
trait Dog { // The dog trait gives some functionality
fn bark(&self) { // It can bark
println!("Woof woof!");
}
fn run(&self) { // and it can run
println!("The dog is running!");
}
}
impl Dog for Animal {
fn run(&self) {
println!("{} is running!", self.name);
}
}
fn main() {
let rover = Animal {
name: "Rover".to_string(),
};
rover.bark(); // Now Animal can use bark()
rover.run(); // and it can use run()
}
</code></pre></pre>
<p>Now it prints <code>Rover is running!</code>. This is okay because we are returning <code>()</code>, or nothing, which is what the trait says.</p>
<p>When you are writing a trait, you can just write the function signature. But if you do that, the user will have to write the function. Let's try that. Now we change <code>bark()</code> and <code>run()</code> to just say <code>fn bark(&self);</code> and <code>fn run(&self);</code>. This is not a full function, so the user must write it.</p>
<p>So when you create a trait, you must think: "Which functions should I write? And which functions should the user write?" If you think the user should use the function the same way every time, then write out the function. If you think the user will use it differently, then just write the function signature.</p>
<p>So let's try implementing the Display trait for our struct. First we will make a simple struct:</p>
println!("Mr. Mantle is a {:?}", mr_mantle);
}
</code></pre></pre>
<p>but Debug print is not the prettiest way to print, because it looks like this.</p>
<pre><codeclass="language-text">Mr. Mantle is a Cat { name: "Reggie Mantle", age: 4 }
</code></pre>
<p>So we need to implement <code>Display</code> for <code>Cat</code> if we want nicer printing. On <ahref="https://doc.rust-lang.org/std/fmt/trait.Display.html">https://doc.rust-lang.org/std/fmt/trait.Display.html</a> we can see the information for Display, and one example. It says:</p>
<p>Some parts of this we don't understand yet, like <code><'_></code> and what <code>f</code> is doing. But we understand the <code>Position</code> struct: it is just two <code>f32</code>s. We also understand that <code>self.longitude</code> and <code>self.latitude</code> are the fields in the struct. So maybe we can just use this code for our struct, with <code>self.name</code> and <code>self.age</code>. Also, <code>write!</code> looks a lot like <code>println!</code> so it is pretty familiar. So we write this:</p>
write!(f, "{} is a cat who is {} years old.", self.name, self.age)
}
}
fn main() {
let mr_mantle = Cat {
name: "Reggie Mantle".to_string(),
age: 4,
};
println!("{}", mr_mantle);
}
</code></pre></pre>
<p>Success! Now when we use <code>{}</code> to print, we get <code>Reggie Mantle is a cat who is 4 years old.</code>. This looks much better.</p>
<p>By the way, if you implement <code>Display</code> then you get the <code>ToString</code> trait for free. That's because you use the <code>format!</code> macro for the <code>.fmt()</code> function, which lets you make a <code>String</code> with <code>.to_string()</code>. So we could do something like this where we pass <code>reggie_mantle</code> to a function that wants a <code>String</code>, or anything else.</p>
write!(f, "{} is a cat who is {} years old.", self.name, self.age)
}
}
fn print_cats(pet: String) {
println!("{}", pet);
}
fn main() {
let mr_mantle = Cat {
name: "Reggie Mantle".to_string(),
age: 4,
};
print_cats(mr_mantle.to_string()); // Turn him into a String here
println!("Mr. Mantle's String is {} letters long.", mr_mantle.to_string().chars().count()); // Turn him into chars and count them
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">Reggie Mantle is a cat who is 4 years old.
Mr. Mantle's String is 42 letters long.
</code></pre>
<p>The thing to remember about traits is that they are about the behaviour of something. How does your <code>struct</code> act? What can it do? That's what traits are for. If you think of some of the traits we've seen so far, they are all about behaviour: <code>Copy</code> is something that a type can do. <code>Display</code> is also something that a type can do. <code>ToString</code> is another trait, and it's also something that a type can do: it can change into a <code>String</code>. In our <code>Dog</code> trait the word <em>dog</em> doesn't mean something you can do, but it gives some methods that let it do things. You could also implement it for a <code>struct Poodle</code> or <code>struct Beagle</code> and they would all get <code>Dog</code> methods.</p>
<p>Let's look at another example that is even more connected to just behaviour. We'll imagine a fantasy game with some simple characters. One is a <code>Monster</code>, the other two are <code>Wizard</code> and <code>Ranger</code>. The <code>Monster</code> just has <code>health</code> so we can attack it, the other two don't have anything yet. But we made two traits. One is called <code>FightClose</code>, and lets you fight up close. The other is <code>FightFromDistance</code>, and lets you fight from far away. Only <code>Ranger</code> can use <code>FightFromDistance</code>. Here's what it looks like:</p>
"You attack with your rock. Your opponent now has {} health left.",
opponent.health
);
}
}
impl FightFromDistance for Ranger {}
fn main() {
let radagast = Wizard {};
let aragorn = Ranger {};
let mut uruk_hai = Monster { health: 40 };
radagast.attack_with_sword(&mut uruk_hai);
aragorn.attack_with_bow(&mut uruk_hai, 8);
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">You attack with your sword. Your opponent now has 30 health left.
You attack with your bow. Your opponent now has 20 health left.
</code></pre>
<p>We pass <code>self</code> inside our trait all the time, but we can't do much with it right now. That's because Rust doesn't know what type is going to use it. It could be a <code>Wizard</code>, it could be a <code>Ranger</code>, it could be a new struct called <code>Toefocfgetobjtnode</code> or anything else. To give <code>self</code> some functionality, we can add necessary traits to the trait. If we want to print with <code>{:?}</code> for example then we need <code>Debug</code>. You can add it to the trait just by writing it after <code>:</code> (a colon). Now our code looks like this:</p>
"You attack with your sword. Your opponent now has {} health left. You are now at: {:?}", // We can now print self with {:?} because we have Debug
"You attack with your rock. Your opponent now has {} health left. You are now at: {:?}",
opponent.health, self
);
}
}
impl FightFromDistance for Ranger {}
fn main() {
let radagast = Wizard { health: 60 };
let aragorn = Ranger { health: 80 };
let mut uruk_hai = Monster { health: 40 };
radagast.attack_with_sword(&mut uruk_hai);
aragorn.attack_with_bow(&mut uruk_hai, 8);
}
</code></pre></pre>
<p>Now this prints:</p>
<pre><codeclass="language-text">You attack with your sword. Your opponent now has 30 health left. You are now at: Wizard { health: 60 }
You attack with your bow. Your opponent now has 20 health left. You are now at: Ranger { health: 80 }
</code></pre>
<p>In a real game it might be better to rewrite this for each type, because <code>You are now at: Wizard { health: 60 }</code> looks funny. That's also why methods inside traits are usually simple, because you don't know what type is going to use it. You can't write things like <code>self.0 += 10</code> for example. But this example shows that we can use other traits inside a trait we are writing. And when we do that, we get some methods that we can use.</p>
<p>One other way to use a trait is with what are called <code>trait bounds</code>. That means "limitations by a trait". Trait bounds are easy because a trait actually doesn't need any methods, or anything at all. Let's rewrite our code with something similar but different. This time our trait doesn't have any methods, but we have other functions that require traits to use.</p>
<pre><preclass="playground"><codeclass="language-rust">use std::fmt::Debug; // So we don't have to write std::fmt::Debug every time now
struct Monster {
health: i32,
}
#[derive(Debug)]
struct Wizard {
health: i32,
}
#[derive(Debug)]
struct Ranger {
health: i32,
}
trait Magic{} // No methods for any of these traits. They are just trait bounds
trait FightClose {}
trait FightFromDistance {}
impl FightClose for Ranger{} // Each type gets FightClose,
impl FightClose for Wizard {}
impl FightFromDistance for Ranger{} // but only Ranger gets FightFromDistance
impl Magic for Wizard{} // and only Wizard gets Magic
<pre><codeclass="language-text">You attack with your sword. Your opponent now has 30 health left. You are now at: Wizard { health: 60 }
You attack with your bow. Your opponent now has 20 health left. You are now at: Ranger { health: 80 }
You raise your hands and cast a fireball! Your opponent now has 0 health left. You are now at: Wizard { health: 60 }
</code></pre>
<p>So you can see there are many ways to do the same thing when you use traits. It all depends on what makes the most sense for the program that you are writing.</p>
<p>Now let's look at how to implement some of the main traits you will use in Rust.</p>
<p><em>From</em> is a very convenient trait to use, and you know this because you have seen it so much already. With <em>From</em> you can make a <code>String</code> from a <code>&str</code>, but you can make many types from many other types. For example, Vec uses <em>From</em> for the following:</p>
<p>If you look at the type, the second and third vectors are <code>Vec<u8></code>, which means the bytes of the <code>&str</code> and the <code>String</code>. So you can see that <code>From</code> is very flexible and used a lot. Let's try it with our own types.</p>
<p>We'll make two structs and then implement <code>From</code> for one of them. One struct will be <code>City</code>, and the other will be <code>Country</code>. We want to be able to do this: <code>let country_name = Country::from(vector_of_cities)</code>.</p>
<p>It looks like this:</p>
<pre><preclass="playground"><codeclass="language-rust">#[derive(Debug)] // So we can print City
struct City {
name: String,
population: u32,
}
impl City {
fn new(name: &str, population: u32) -> Self { // just a new function
Self {
name: name.to_string(),
population,
}
}
}
#[derive(Debug)] // Country also needs to be printed
struct Country {
cities: Vec<City>, // Our cities go in here
}
impl From<Vec<City>> for Country { // Note: we don't have to write From<City>, we can also do
// From<Vec<City>>. So we can also implement on a type that
// we didn't create
fn from(cities: Vec<City>) -> Self {
Self { cities }
}
}
impl Country {
fn print_cities(&self) { // function to print the cities in Country
for city in &self.cities {
// & because Vec<City> isn't Copy
println!("{:?} has a population of {:?}.", city.name, city.population);
}
}
}
fn main() {
let helsinki = City::new("Helsinki", 631_695);
let turku = City::new("Turku", 186_756);
let finland_cities = vec![helsinki, turku]; // This is the Vec<City>
let finland = Country::from(finland_cities); // So now we can use From
finland.print_cities();
}
</code></pre></pre>
<p>This prints:</p>
<pre><codeclass="language-text">"Helsinki" has a population of 631695.
"Turku" has a population of 186756.
</code></pre>
<p>You can see that <code>From</code> is easy to implement from types you didn't create like <code>Vec</code>, <code>i32</code>, and so on. Here is one more example where we create a vector that has two vectors. The first vector holds even numbers, and the second holds odd numbers. With <code>From</code> you can give it a vector of <code>i32</code>s and it will turn it into a <code>Vec<Vec<i32>></code>: a vector that holds vectors of <code>i32</code>.</p>
<p>A type like <code>EvenOddVec</code> is probably better as a generic <code>T</code> so we can use many number types. You can try to make the example generic if you want for practice.</p>
<h3id="taking-a-string-and-a-str-in-a-function"><aclass="header"href="#taking-a-string-and-a-str-in-a-function">Taking a String and a &str in a function</a></h3>
<p>Sometimes you want a function that can take both a <code>String</code> and a <code>&str</code>. You can do this with generics and the <code>AsRef</code> trait. <code>AsRef</code> is used to give a reference from one type to another type. If you look at the documentation for <code>String</code>, you can see that it has <code>AsRef</code> for many types:</p>
<p>You can see that it takes <code>&self</code> and gives a reference to the other type. This means that if you have a generic type T, you can say that it needs <code>AsRef<str></code>. If you do that, it will be able to take a <code>&str</code> and a <code>String</code>.</p>
<p>Let's start with the generic function. This doesn't work yet:</p>
<p>Now it works and prints <code>Please print me</code>. That is good, but T can still be too many things. It can be an <code>i8</code>, an <code>f32</code> and anything else with just <code>Display</code>. So we add <code>AsRef<str></code>, and now T needs both <code>AsRef<str></code> and <code>Display</code>.</p>
<p>Now it won't take types like <code>i8</code>.</p>
<p>Don't forget that you can use <code>where</code> to write the function differently when it gets long. If we add Debug then it becomes <code>fn print_it<T: AsRef<str> + Display + Debug>(input: T)</code> which is long for one line. So we can write it like this:</p>