# Adding Behavior

#### `impl` blocks

We can add behavior to individual types with a simple `impl` block:

\`struct BasicGreeter { greeting: String, }

impl BasicGreeter { fn greet(\&self, name: \&str) { println!("{}, {name}!", self.greeting); } }

let g = BasicGreeter { greeting: "Welcome".to\_string(), }; g.greet("John");\`

Output:

`Welcome, John!`

The `&self` parameter is special: it causes a function to be a method, operating on an instance of a type, as opposed to an associated function, which does not necessarily operate on an instance. In object-oriented terms, functions that take a `self` parameter (or any of the variants) are like instance methods, and functions that do not are like static methods.

#### Traits

Traits are the primary form of abstraction in Rust. A trait describes a set of behaviors that a type implements. It’s very similar to an interface in a language like Java. Actually, we’ve been using some traits already, in a subtle sort of way.

Remember how to print things to the screen? `println!(...)`? As you probably noticed by now, we can print a bunch of different things. Numbers, strings, booleans, etc.

`println!("{}, {}, {}, {}", "hello", 42, 3.14, true);`

This is an example of abstraction: all of the different types all support the behavior of “being printed.”

In Rust, this behavior is described by the `[Display](<https://doc.rust-lang.org/std/fmt/trait.Display.html>)` trait, which is like adding a `toString` method to a class in Java.[5](http://localhost:1313/blog/rust-quickstart-for-javascript-programmers/#fn:5)

All of these types (`String`, `&str`, `u32`, `f32`, `bool`, …) implement `Display`.

Let’s take a look at writing a trait and implementing it.

\`// create a trait trait Greeter { fn greet(\&self, name: \&str); }

struct MorningGreeter;

// implement the trait on MorningGreeter impl Greeter for MorningGreeter { fn greet(\&self, name: \&str) { println!("Good morning, {name}!"); } }

struct EveningGreeter;

// implement the trait on EveningGreeter impl Greeter for EveningGreeter { fn greet(\&self, name: \&str) { println!("Good evening, {name}!"); } }

let g1 = MorningGreeter; g1.greet("Alice"); // -> Good morning, Alice!

let g2 = EveningGreeter; g2.greet("Bob"); // -> Good evening, Bob!\`

This isn’t terribly interesting yet. Let’s spice it up some.

\`fn greet\_wizard\<G: Greeter>(g: G) { g.greet("Gandalf"); }

greet\_wizard(EveningGreeter); // -> Good evening, Gandalf!\`

This uses a [generic type parameter](https://doc.rust-lang.org/book/ch10-01-syntax.html) to allow us to pass it any parameter that implements the `Greeter` trait. If you’re familiar with Java, etc., the angle bracket `<>` syntax might look familiar.

The colon in `G: Greeter` means “`G` *implements* `Greeter`.” You can specify multiple [trait bounds](https://doc.rust-lang.org/reference/trait-bounds.html) using a `+`, like so: `T: Debug + Display`.

If you have too many generic parameters, or if the bounds are too complex, you can move them to a `where` clause to organize your function signature a little:

`fn my_function<T>(t: T) where T: Send + Sync {}`

If you don’t need to refer to the generic parameter by name, you can use a shorthand:

\`fn greet\_wizard(g: impl Greeter) { g.greet("Gandalf"); }

greet\_wizard(EveningGreeter); // -> Good evening, Gandalf!\`

This code is identical to the previous `greet_wizard` example, but it’s a little easier to read, since there’s no `G` generic parameter floating around.

#### Trait objects

There’s another way to accept parameters based on what traits they implement, as opposed to by concrete type. Using the `dyn` keyword, we can create a [trait object](https://doc.rust-lang.org/reference/types/trait-object.html). It’s a bit of a hairy topic if you dive deeply into it, but for now, keep in mind the following properties:

* `dyn Trait` is [unsized](https://doc.rust-lang.org/reference/dynamically-sized-types.html), meaning you usually can’t work with it directly, since the compiler cannot know how big it is.
* Therefore, trait objects are usually used behind some form of pointer, either regular (`&dyn Trait`) or smart (`Box<dyn Trait>`).
* Trait objects include a [vtable](https://en.wikipedia.org/wiki/Virtual_method_table), which can make function access a tiny bit slower. Usually, Rust’s [monomorphized](https://en.wikipedia.org/wiki/Monomorphization) generics are preferred, since they can be optimized per-type, and also preserve type information across the codebase.

#### Drop&#x20;

Called automatically when an object goes out of scope. The main use of the `Drop` trait is to free the resources that the implementor instance owns.
