Rust by Example - страница 39

стр.

>

>trait Blue {}

>impl Red for Cardinal {}

>impl Blue for BlueJay {}

>// These functions are only valid for types which implement these

>// traits. The fact that the traits are empty is irrelevant.

>fn red(_: &T) -> &'static str { "red" }

>fn blue(_: &T) -> &'static str { "blue" }

>fn main() {

>let cardinal = Cardinal;

>let blue_jay = BlueJay;

>let _turkey = Turkey;

>// `red()` won't work on a blue jay nor vice versa

>// because of the bounds.

>println!("A cardinal is {}", red(&cardinal));

>println!("A blue jay is {}", blue(&blue_jay));

>//println!("A turkey is {}", red(&_turkey));

>// ^ TODO: Try uncommenting this line.

>}

>הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Multiple bounds can be applied with a +. Like normal, different types are separated with ,.

>use std::fmt::{Debug, Display};

>fn compare_prints(t: &T) {

>println!("Debug: `{:?}`", t);

>println!("Display: `{}`", t);

>}

>fn compare_types(t: &T, u: &U) {

>println!("t: `{:?}`", t);

>println!("u: `{:?}`", u);

>}

>fn main() {

>let string = "words";

>let array = [1, 2, 3];

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

>compare_prints(&string);

>//compare_prints(&array);

>// TODO ^ Try uncommenting this.

>compare_types(&array, &vec);

>}

>הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

A bound can also be expressed using a where clause immediately before the opening {, rather than at the type's first mention. Additionally, where clauses can apply bounds to arbitrary types, rather than just to type parameters.

Some cases that a where clause is useful:

   • When specifying generic types and bounds separately is clearer:

>impl MyTrait for YourType {}


>// Expressing bounds with a `where` clause

>impl MyTrait 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 PrintInOption for T where

>Option: Debug {

>// We want `Option: 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