# Traits and Generics

**Polymorphism**: 多态 in Chinese. Rust supports polymorphism with two features: traits and generics.

```rust
use std::io::Write;

fn say_hello(out: &mut dyn Write) -> std::io::Result<()> {
  out.write_all(b"hello world\n")?;
  out.flush()
}
```

The type of `out` is `&mut dyn Write`, meaning “a mutable reference to any value that implements the `Write` trait.”

## Using Traits

**Examples**:

* A value that implements `std::io::Write` can write out bytes.
* A value that implements `std::iter::Iterator` can produce a sequence of values.
* A value that implements `std::clone::Clone` can make clones of itself in memory.
* A value that implements `std::fmt::Debug` can be printed using `println!()` with the `{:?}` format specifier.

The trait itself must be in scope. Otherwise, all its methods are hidden. Some traits has been imported implicitly as part of the standard prelude.

```rust
use std::io::Write;

let mut buf: Vec<u8> = vec![];
buf.write_all(b"hello")?;  // ok
```

The calls to `write_alls` are statically decided, resulting in low overhead. However, the calls through `&mut dyn Write` incur the overhead of a dynamic dispatch, also known as a virtual method call, which is indicated by the `dyn` keyword in the type.

There are two ways of using traits to write polymorphic code in Rust: **trait objects** and **generics**.

### Trait Objects

Rust doesn’t permit variables of type `dyn Write`:

```rust
use std::io::Write;

let mut buf: Vec<u8> = vec![];
let writer: dyn Write = buf;  // error: `Write` does not have a constant size
let writer: &mut dyn Write = &mut buf;  // ok
```

A variable’s size has to be known at compile time, and types that implement `Write` can be any size. (Since `dyn Write` could potentially refer to any type implementing the `Write` trait, its size is not fixed).

A reference to a trait type, like `writer`, is called a *trait object*. Like any other reference, a trait object points to some value, it has a lifetime, and it can be either `mut` or shared.

What makes a trait object different is that Rust usually doesn’t know the type of the referent at compile time.

**Memory Representation**

A trait object in memory is a fat pointer that includes two components: a pointer to the actual value and a pointer to a table that represents the value's type. Because of this, a trait object occupies two machine words. The trait object (indicated by `&dyn`, which is a fat pointer) differs from a regular reference, which is just a bare pointer. In other words, `&dyn` and `&` are distinct types.

<figure><img src="https://p.ipic.vip/ixbzca.png" alt="A diagram showing trait objects in memory."><figcaption></figcaption></figure>

> In C++, the vtable pointer, or *vptr*, is stored as part of the struct. Rust uses fat pointers instead. This way, a struct can implement dozens of traits without containing dozens of vptrs.

**Auto Conversion**

Rust automatically converts ordinary references into trait objects when needed.

```rust
let mut local_file = File::create("hello.txt")?;
say_hello(&mut local_file)?;
```

The type of `&mut local_file` is `&mut File`, and the type of the argument to `say_hello` is `&mut dyn Write`. Since a `File` is a kind of writer, Rust allows this, automatically converting the plain reference to a trait object.

Likewise, Rust will happily convert a `Box<File>` to a `Box<dyn Write>`, a value that owns a writer in the heap:

```rust
let w: Box<dyn Write> = Box::new(local_file);
```

`Box<dyn Write>`, like `&mut dyn Write`, is a fat pointer: it contains the address of the writer itself and the address of the vtable. The same goes for other pointer types, like `Rc<dyn Write>`.

### Generic Functions and Type Parameters

```rust
fn say_hello<W: Write>(out: &mut W) -> std::io::Result<()> {
    out.write_all(b"hello world\n")?;
    out.flush()
}
```

When you pass `&mut local_file` to the generic `say_hello()` function, you’re calling `say_hello::<File>()`. Rust infers the type `W` from the type of the argument and generate machine code for the calls to the corresponding versions of functions. This process is known as *monomorphization* (单态化), and the compiler handles it all automatically.

***

```rust
use std::hash::Hash;
use std::fmt::Debug;

fn top_ten<T: Debug + Hash + Eq>(values: &Vec<T>) { ... }
```

<figure><img src="https://learning.oreilly.com/api/v2/epubs/urn:orm:book:9781492052586/files/assets/pr2e_1102.png" alt="A Venn diagram shows the three sets of types."><figcaption></figcaption></figure>

A generic function can have both lifetime parameters and type parameters. Lifetime parameters come first.

```rust
/// Return a reference to the point in `candidates` that's
/// closest to the `target` point.
fn nearest<'t, 'c, P>(target: &'t P, candidates: &'c [P]) -> &'c P
    where P: MeasureDistance
{
    ...
}
```

In addition to types and lifetimes, generic functions can take **constant parameters** as well.

```rust
fn dot_product<const N: usize>(a: [f64; N], b: [f64; N]) -> f64 {
    let mut sum = 0.;
    for i in 0..N {
        sum += a[i] * b[i];
    }
    sum
}
```

### Trait Objects or Generic Code?

Sometimes you want to manage a group of objects of different types - but implementing the same trait, it's not a good idead to use generic code, which is hard to express "objects of different types". Check out the example from the book:

```rust
trait Vegetable {
    ...
}

struct Salad<V: Vegetable> {
    veggies: Vec<V>
}
```

The `Vec` can only hold objects of the same type `V`, which might be `IcebergLettuce`, which is not ideal for the need that `veggies` should contain vegetables of different types.

In contrast, you can use trait objects:

```rust
struct Salad {
    veggies: Vec<Box<dyn Vegetable>>
}
```

Use trait objects can also reduce the total amount of compiled code.

***

Outside of situations involving salad or low-resource environments, generics have three important advantages over trait objects, resulting in generics being the more common choice.

* **Speed**: The `dyn` keyword isn’t used because there are no trait objects—and thus no dynamic dispatch—involved.
* **Not every trait can support trait objects**
* **Easy to bound a generic type parameter with several traits at once**: types like `&mut (dyn Debug + Hash + Eq)` aren’t supported in Rust.

## Defining and Implementing Traits

```rust
trait Visible {
  fn draw(&self, canvas: &mut Canvas);
}

impl Brrom {
  /// Helper function used by Broom::draw() below.
}

impl Visible for Broom {
    fn draw(&self, canvas: &mut Canvas) {
      ...
  	}
}
```

Traits can also include default implementation.

You can use a generic `impl` block to add an extension trait to a whole family of types at once.

### Self in Traits

```rust
pub trait Spliceable {
    fn splice(&self, other: &Self) -> Self;
}
```

Using `Self` as the return type here means that the type of `x.clone()` is the same as the type of `x`.

```rust
impl Spliceable for CherryTree {
    fn splice(&self, other: &Self) -> Self {
        ...
    }
}
```

`Self` is an alias for the type of struct.

**A trait that uses the `Self` type is incompatible with trait objects.**

```rust
// error: the trait `Spliceable` cannot be made into an object
// This calls back to the statement that not every trait can support trait objects.
fn splice_anything(left: &dyn Spliceable, right: &dyn Spliceable) {
    let combo = left.splice(right);
    // ...
}
```

Rust rejects this code because it has no way to type-check the call `left.splice(right)`. The whole point of trait objects is that the type isn’t known until run time. Rust has no way to know at compile time if `left` and `right` will be the same type, as required.

But we can design a **trait-object-friendly** trait:

```rust
pub trait MegaSpliceable {
    fn splice(&self, other: &dyn MegaSpliceable) -> Box<dyn MegaSpliceable>;
}
```

### Subtraits

Say that `Creature` is a *subtrait* of `Visible`, and that `Visible` is `Creature`’s *supertrait*. Subtraits extend the functionality of their supertraits. Every type that implements `Creature` must also implement the `Visible` trait.

```rust
/// Someone in the game world, either the player or some other
/// pixie, gargoyle, squirrel, ogre, etc.
trait Creature: Visible {
    fn position(&self) -> (i32, i32);
    fn facing(&self) -> Direction;
    ...
}

impl Visible for Broom {
    ...
}

impl Creature for Broom {
    ...
}
```

The syntax of subtraits can be experssed in the following fashion also:

```rust
trait Creature where Self: Visible {
    ...
}
```

### Type-Associated Functions

Traits can include type-associated functions, Rust’s analog to **static methods**.

```rust
trait StringSet {
    /// Return a new empty set.
    fn new() -> Self;

    /// Return a set that contains all the strings in `strings`.
    fn from_slice(strings: &[&str]) -> Self;

    /// Find out if this set contains a particular `value`.
    fn contains(&self, string: &str) -> bool;

    /// Add a string to this set.
    fn add(&mut self, string: &str);
}
```

`from_slice` and `new` don't take a `self` argument. These functions can be called using `::` syntax, just like any other type-associated function.

## Fully Qualified Method Calls

**Fully qualified method calls** tell your intention precisely by specifying the exact method we can calling.

```rust
"hello".to_string()
str::to_string("hello")
ToString::to_string("hello")
<str as ToString>::to_string("hello") // This is the fully qualified method call.
```

> The `.` operator does not say exactly which `to_string` method we are calling and Rust has a method to lookup algorithm that figures this out.

**Application**:

* There are methods with the same name from different traits:

  ```rust
  outlaw.draw();  // error: draw on screen or draw pistol?

  Visible::draw(&outlaw);  // ok: draw on screen
  HasPistol::draw(&outlaw);  // ok: corral
  ```
* When the type of the `self` argument can’t be inferred:

  ```rust
  let zero = 0;  // type unspecified; could be `i8`, `u8`, ...
  zero.abs();  // error: can't call method `abs`
               // on ambiguous numeric type
  i64::abs(zero);  // ok
  ```
* When using the function itself as a function value:

  ```rust
  let words: Vec<String> =
      line.split_whitespace()  // iterator produces &str values
          .map(ToString::to_string)  // ok
          .collect();
  ```
* When calling trait methods in macros.

## Traits That Define Relationships Between Types

The standard `Iterator` trait of Rust:

```rust
pub trait Iterator {
  type Item;
  
  fn next(&mut self) -> Opiton<Self::Item>;
}
```

* `type Item;` is an ***associated type***. Each type that implements `Iterator` must specify what type of item it produces.

To implement `Iterator` for a type:

```rust
// (code from the std::env standard library module)
impl Iterator for Args {
  type Item = String;
  
  fn next(&mut self) -> Option<String> {
    ...
  }
  ...
}
```

`std::env::Args` is the type of iterator returned by the standard library function `std::env::args()`. It produces `String` values.

***

Generic code can use associated types:

```rust
fn collect_into_vector<I: Iterator>(iter: I) -> Vec<I::Item> {
  let mut results = Vec::new();
  for value in iter {
    results.push(value);
  }
  results
}
```

Rust can infer the type of `value` inside the function, but we still need to sepcify the type of the return value. You can also write the generic code in the following manner:

```rust
fn dump<I>(iter: I) where I: Iterator<Item=String> {
  ...
}

// or

fn dump(iter: &mut dyn Iterator<Item=String>) {
  for (index, s) in iter.enumerate() {
    println("{}: {:?}", index, s);
  }
}
```

### Generic Traits (or How Operator Overloading Works)

```rust
/// The std::ops::Mul trait, which allows types to support the `*` operator
pub trait Mul<RHS=Self> {
  /// The resulting type after applying the `*` operator
  type Output;
  
  /// The method that defines the behavior of the `*` operator
  fn mul(self, rhs: RHS) -> Self::Output;
}
```

* As shown, the `Self` type is associated with and used by the definitions of traits.
* While traits are typically used to enable polymorphism, they can themselves be designed with polymorphic behavior, allowing for multiple variants or implementations.

This is a generic trait, the instances of which correspond to the underlying type of `RHS`. For instance, `Mul<String>` and `Mul<u64>` are different types. Therefore, a single type—say, `WindowSize`—can implement both `Mul<f64>` and `Mul<i32>`, and many more.

The syntax `RHS=Self` means that `RHS` defaults to `Self`.

### Return `impl Trait`

We can simplify the return type of a function by specifying the trait or traits that the return value implements:

```rust
fn cyclical_zip(v: Vec<u8>, u: Vec<u8>) -> impl Iterator<Item=u8> {
    v.into_iter().chain(u.into_iter()).cycle()
}
```

However, you cannot use `impl Trait` to implement the factory pattern directly:

```rust
trait Shape {
    fn new() -> Self;
    fn area(&self) -> f64;
}

fn make_shape(shape: &str) -> impl Shape {
    match shape {
        "circle" => Circle::new(),
        "triangle" => Triangle::new(),
        "rectangle" => Rectangle::new(),
    }
}
```

In the first example, the return type is clear because `v` and `u` are both `Vec<u8>`, so the function returns an iterator over `u8`. However, in the second example, the return type could be `Circle`, `Triangle`, or `Rectangle`, which means the return type is not uniquely determined.

Additionally, `impl Trait` can only be used in free functions (i.e., functions not associated with a trait) or in methods associated with specific types, but not in trait methods themselves. This limitation exists because the return type of a trait method must be explicitly known and consistent across all implementations of the trait.

### Associated Consts

Like structs and enums, traits can have associated constants. You can declare a trait with an associated constant using the same syntax as for a struct or enum:

```rust
trait Greet {
  const GREETING: &'static str = "Hello";
  fn greet(&self) -> String;
}
```

This allows you to write generic code that uses these values:

```rust
fn add_one<T: Float + Add<Output=T>>(value: T) -> T {
  value + T::ONE
}
```

Associated constants can’t be used with trait objects, since the compiler relies on type information about the implementation to pick the right value at compile time.


---

# 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://osh.fducslg.com/notes/rust/traits-and-generics.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.
