Выбрать главу

impl <A, D> MyTrait<A, D> for YourType where

A: TraitB + TraitC,

D: TraitE + TraitF {}

   • When using a where clause is more expressive than using normal syntax. The impl in this example cannot be directly expressed without a where clause:

use std::fmt::Debug;

trait PrintInOption {

fn print_in_option(self);

}

// Because we would otherwise have to express this as `T: Debug` or

// use another method of indirect approach, this requires a `where` clause:

impl<T> PrintInOption for T where

Option<T>: Debug {

// We want `Option<T>: Debug` as our bound because that is what's

// being printed. Doing otherwise would be using the wrong bound.

fn print_in_option(self) {

println!("{:?}", Some(self));

}

}

fn main() {

let vec = vec![1, 2, 3];

vec.print_in_option();

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

RFC, struct, and trait

The newtype idiom gives compile time guarantees that the right type of value is supplied to a program.

For example, an age verification function that checks age in years, must be given a value of type Years.

struct Years(i64);

struct Days(i64);

impl Years {

pub fn to_days(&self) -> Days {

Days(self.0 * 365)

}

}

impl Days {

/// truncates partial years

pub fn to_years(&self) -> Years {

Years(self.0 / 365)

}

}

fn old_enough(age: &Years) -> bool {

age.0 >= 18

}

fn main() {

let age = Years(5);

let age_days = age.to_days();

println!("Old enough {}", old_enough(&age));

println!("Old enough {}", old_enough(&age_days.to_years()));

// println!("Old enough {}", old_enough(&age_days));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Uncomment the last print statement to observe that the type supplied must be Years.

To obtain the newtype's value as the base type, you may use tuple syntax like so:

struct Years(i64);

fn main() {

let years = Years(42);

let years_as_primitive: i64 = years.0;

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

structs

"Associated Items" refers to a set of rules pertaining to items of various types. It is an extension to trait generics, and allows traits to internally define new items.

One such item is called an associated type, providing simpler usage patterns when the trait is generic over its container type.

RFC

A trait that is generic over its container type has type specification requirements - users of the trait must specify all of its generic types.

In the example below, the Contains trait allows the use of the generic types A and B. The trait is then implemented for the Container type, specifying i32 for A and B so that it can be used with fn difference().

Because Contains is generic, we are forced to explicitly state all of the generic types for fn difference(). In practice, we want a way to express that A and B are determined by the input C. As you will see in the next section, associated types provide exactly that capability.

struct Container(i32, i32);

// A trait which checks if 2 items are stored inside of container.

// Also retrieves first or last value.

trait Contains<A, B> {

fn contains(&self, _: &A, _: &B) -> bool; // Explicitly requires `A` and `B`.

fn first(&self) -> i32; // Doesn't explicitly require `A` or `B`.

fn last(&self) -> i32; // Doesn't explicitly require `A` or `B`.