> For the complete documentation index, see [llms.txt](https://bagus-cahyono.gitbook.io/programming-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bagus-cahyono.gitbook.io/programming-notes/rust/generics_and_traits.md).

# 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)
