# Generics & Traits

By using **Generics** and **Traits** we can leverage their combined power to write efficient, reusable, and type-safe code.

## Generics

* Generics used to create definitions for items like function signatures or structs, which we can then use with many different concrete data types.
* So instead of writing separate implementations for each type, you define a generic type that can be substituted with concrete types when the code is used.
* Represented by angle brackets (`<>`) and often denoted by `T`, `U`, or other descriptive names.
* Generics in Rust are resolved at compile time, ensuring that invalid types cannot be used.
* Rust generates optimized code for each concrete type used with a generic at compile time, avoiding runtime overhead.

### Generic Functions

* Functions can use generics to operate on multiple types.

  ```rust
  fn hello<T: std::fmt::Display>(name: T) {
      println!("hello {}!", name);
  }

  fn main() {
      hello(777);
      hello("World");
  }
  ```

### Generic Structs

* Structs can hold values of any type using generics.

  ```rust
  struct Point<T> {
      x: T,
      y: T,
  }

  let int_point = Point { x: 1, y: 2 };
  let float_point = Point { x: 1.7, y: 2.4 };
  ```

### Generic Enums

* Enums can also use generics, as seen with Option or Result.

  ```rust
  enum Option<T> {
      Some(T),
      None,
  }

  let int_option: Option<i32> = Option::Some(10);
  let float_option: Option<f64> = Option::Some(5.7);
  ```

## Traits

* A trait is similar to an interface in other programming languages.
* It defines a set of methods that a type must implement, allowing you to specify what functionality a type provides without dictating how it provides it.
* Implementing a trait on a type is similar to implementing regular methods.
* The difference is that after `impl`, we put the trait name we want to implement, then use the `for` keyword, and then specify the name of the type we want to implement the trait for.
* Traits can provide default method implementations that types can override.
* The `impl Trait` syntax works for straightforward cases but is actually syntax sugar for a longer form known as a trait bound.
* We can also specify more than one trait bound using `+` syntax.

### Defining a Trait

* A trait defines methods that other types can implement.

  ```rust
  trait Summary {
      fn summarize(&self) -> String;
  }
  ```

## Implementing a Trait

* Implementing a trait similar like implementing method by put the trait name after `impl` and then specify the type after `for`.

  ```rust
  struct NewsArticle {
      headline: String,
      location: String,
      author: String,
      content: String,
  }

  impl Summary for NewsArticle {
      fn summarize(&self) -> String {
          format!("{}, by {} ({})", self.headline, self.author, self.location)
      }
  }

  struct Tweet {
      username: String,
      content: String,
      reply: bool,
      retweet: bool,
  }

  impl Summary for Tweet {
      fn summarize(&self) -> String {
          format!("{}: {}", self.username, self.content)
      }
  }
  ```

## Default Implementation

* Traits can provide default method implementations that types can override.

  ```rust
  trait Summary {
      fn summarize(&self) -> String {
          "Default Summary".to_string()
      }
  }
  ```

## Traits as Parameters

* Traits can be used as parameters using `impl Trait` syntax.

  ```rust
  fn notify(item: &impl Summary) {
      println!("Breaking news! {}", item.summarize());
  }
  ```
* The `impl Trait` syntax works for straightforward cases but is actually syntax sugar for a longer form known as a trait bound; it looks like this:

  ```rust
  pub fn notify<T: Summary>(item: &T) {
      println!("Breaking news! {}", item.summarize());
  }
  ```
* We also can have multiple parameters that implement a trait.
* For example this function have two parameters that implement Summary:

  ```rust
  pub fn notify(item1: &impl Summary, item2: &impl Summary) {
  ```
* We can also do it using generics.
* But in the example below the generic type `T` specified as the type of the `item1` and `item2` parameters constrains the function such that the concrete type of the value passed as an argument for `item1` and `item2` must be the same.

  ```rust
  pub fn notify<T: Summary>(item1: &T, item2: &T) {
  ```
* We can also use the impl Trait syntax in the return position to return a value of some type that implements a trait.

  ```rust
  fn returns_summarizable() -> impl Summary {
      NewsArticle {
          headline: "Good News",
          location: "Indonesia",
          author: "Someone",
          content: "Something",
      }
  }
  ```

### Specifying Multiple Trait Bounds

* We can also specify more than one trait bound using `+` syntax.

  ```rust
  pub fn notify(item: &(impl Summary + Display)) {
  ```
* The `+` syntax is also valid with trait bounds on generic types.

  ```rust
  pub fn notify<T: Summary + Display>(item: &T) {
  ```

### Generic Traits

* Traits can also be generic, allowing them to operate over a range of types.

  ```rust
  trait Magic<T> {
      fn add(&self, other: T) -> T;
  }

  impl Magic<String> for i32 {
      fn add(&self, other: String) -> String {
          format!("{}:{}", self, other)
      }
  }

  fn main() {
      println!("{}", 71.add("Magic".to_string()));
  }
  ```

### Extending Existing Traits

* We can extend existing traits by combining them or adding additional behavior.

  ```rust
  trait Printable: Display {
      fn print(&self) {
          println!("{}", self);
      }
  }

  impl Printable for i32 {}
  impl Printable for String {}

  let number: i32 = 71;
  number.print(); // Output: 42

  let text = String::from("FooBar");
  text.print(); // Output: FooBar
  ```

## References

* [Generic Data Types](https://doc.rust-lang.org/book/ch10-01-syntax.html)
* [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html)
* [Traits](https://doc.rust-lang.org/book/ch10-02-traits.html)
* [Traits - Rust by Example](https://doc.rust-lang.org/rust-by-example/trait.html)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bagus-cahyono.gitbook.io/programming-notes/rust/generics_and_traits.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
