Rust5.2 Generic Types, Traits, and Lifetimes

Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 10: Generic Types, Traits, and Lifetimes

lib.rs

use std::fmt::Display;

//Traits: Defining Shared Behavior
pub trait Summary {
    fn summarize_author(&self) -> String;
    
    // fn summarize(&self) -> String;
    fn summarize(&self) -> String {
        //String::from("(Read more from...)")
        format!("(Read more from {}...)", self.summarize_author())
    }
    
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {//implementing a trait on a type
    // fn summarize(&self) -> String {//implementing a trait method
    //     format!("{}, by {} ({})", self.headline, self.author, self.location)
    // }
    fn summarize_author(&self) -> String {//implementing a trait method
        format!("{}", self.author)
    }
    
}

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

impl Summary for Tweet {//implementing a trait on a type
    fn summarize(&self) -> String {//implementing a trait method
        format!("{}: {}", self.username, self.content)
    }
    fn summarize_author(&self) -> String {//implementing a trait method
        format!("{}", self.username)
    }
    
}

pub fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

pub fn notify_trait_bound<T: Summary>(item: &T) {//trait bound syntax
    println!("Breaking news! {}", item.summarize());
}

pub fn notify_trait_bounds<T: Summary>(item1: &T, item2: &T) {//trait bound syntax
    println!("Breaking news! {}", item1.summarize());
    println!("Breaking news! {}", item2.summarize());
}

pub fn notify_multiple_trait_bounds<T: Summary + Display>(item1: &T, item2: &T) {//trait bound syntax
    println!("Breaking news! {}", item1.summarize());
    println!("Breaking news! {}", item2.summarize());
}

pub fn notify_where_clause<T, U>(item1: &T, item2: &U) 
    where T: Summary + Display,
          U: Summary + Display
{
    println!("Breaking news! {}", item1.summarize());
    println!("Breaking news! {}", item2.summarize());
}

//Returning Types that Implement Traits
fn _returns_summarizable() -> impl Summary {
    //returning a type that implements the Summary trait
    //cannot return different types
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    }
}

struct _Pair<T> {
    x: T,
    y: T,
}

impl <T> _Pair<T> {
    fn _new(x: T, y: T) -> Self {
        Self {
            x,
            y,
        }
    }
    
}

impl <T: Display + PartialOrd> _Pair<T> {//trait bound syntax
    fn _cmp_display(&self) {
        if self.x >= self.y {
            println!("The largest member is x = {}", self.x);
        } else {
            println!("The largest member is y = {}", self.y);
        }
    }
    
}

//blanket implementations
// impl ToString for T {
//     // --snip--
// }

main.rs

use generic_types_traits_and_lifetimes::Summary;
use generic_types_traits_and_lifetimes::Tweet;
use std::fmt::Display;

//Generic Data Types
fn largest_generic<T:std::cmp::PartialOrd + Clone>(list: &[T]) -> &T {
    let mut largest = &list[0];

    for item in list {
        if item > largest { //error: the trait `std::cmp::PartialOrd` is not implemented for `T`
            largest = item;
        }
    }

    largest
}

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

impl Point<i32> {
    fn selfx(&self) -> &i32 {
        &self.x
    }
    
}

impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

impl Point<&str>{
    fn concatenate(&self) -> String {
        format!("{}{}", self.x, self.y)
    }
}

#[derive(Debug)]
struct Point2<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point2<T, U> {
    fn mixup<V, W>(self, other: Point2<V, W>) -> Point2<T, W> {
        Point2 {
            x: self.x,
            y: other.y,
        }
    }
}

//Lifetime Annotations in Struct Definitions
struct _ImportantExcerpt<'a> {
    _part: &'a str,
}

fn main() {
    //remove duplication by extracting the match expression into a function
    let number_list = vec![34, 50, 25, 100, 65];

    // let mut largest = &number_list[0];

    // for number in &number_list {
    //     if number > largest {
    //         largest = number;
    //     }
    // }

    //largest function with generic type
    let result1 = largest(&number_list);

    println!("The largest number is {}", result1);

    //duplication
    let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];

    // let mut largest = &number_list[0];

    // for number in &number_list {
    //     if number > largest {
    //         largest = number;
    //     }
    // }

    //largest function with generic type
    let result2 = largest(&number_list);

    println!("The largest number is {}", result2);


    let str_list = vec!["Hello", "Rust", "World"];
    let result3 = largest_generic(&str_list);
    println!("The largest string is {}", result3);

    //Generic Data Types in Struct Definitions
    let integer = Point { x: 5, y: 10 };
    println!("x,y = {},{}", integer.x, integer.y);
    let float = Point { x: 1.0, y: 4.0 };
    println!("x,y = {},{}", float.x, float.y);
    
    //Generic Data Types in Enum Definitions
    let integer = Option::Some(5);
    let float = Option::Some(5.0);
    let none: Option<i32> = None;
    println!("integer = {:?}, float = {:?}, none = {:?}", integer, float, none);
    println!("integer = {:?}, float = {:?}, none = {:?}", integer, float, none);

    //Generic Data Types in Method Definitions
    let p1 = Point { x: 5, y: 10 };
    let p2 = Point { x: "Hello", y: " Rust" };
    let p3 = Point { x: 5.0, y: 10.0 };
    println!("p1:{}",p1.selfx());
    println!("p2:{}",p2.concatenate());
    println!("p3:{}",p3.distance_from_origin());

    //Generic Data Types in Struct Definitions
    let p4 = Point2 { x: 5, y: 10.4 };
    let p5: Point2<&str, i32> = Point2 {x:"Hello", y:2};
    println!("p4:{:?}",p4.mixup(p5));

    //Traits: Defining Shared Behavior
    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };

    println!("1 new tweet: {}", tweet.summarize());

    //Lifetimes: Ensuring One Borrow Lasts as Long as the Other
    //avoiding dangling references

    // let r;
    // //let b = r;//error: use of possibly uninitialized `r`
    // {
    //     let x = 5;
    //     r = &x;
    // }
    // //borrow checker
    // //println!("r:{}",r);//error: `x` does not live long enough

    let x = 5;
    let r = &x;
    println!("r:{}",r);

    let string1 = String::from("abcd"); 
    let string2 = "xyz";
    let result = longest(string1.as_str(), string2);
    println!("The longest string is {}", result);

    //Lifetime Annotations in Struct Definitions
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let _i = _ImportantExcerpt { _part: first_sentence };

    //Lifetime Elision
    
}

fn largest(list: &[i32]) -> &i32 {//we need to return a reference to the value
    let mut largest = &list[0];

    for number in list {
        if number > largest {
            largest = number;
        }
    }

    largest
}

//Lifetime Annotation Syntax
//'a is a generic lifetime parameter
//&'a str: a string slice that lives for the lifetime 'a
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {//we need to return a reference to the value
    //'a is the part of the scope of x that overlaps with the scope of y
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn _longest<'a>(x: &'a str, _y: &str) -> &'a str {//we need to return a reference to the value
    //'a is the part of the scope of x that overlaps with the scope of y
    x
}

// fn error_longest<'a>(x: &str, _y: &str) -> &'a str {//we need to return a reference to the value
//     let result = String::from("really long string");
//     result.as_str()
// }

fn _corroct_longest<'a>(_x: &'a str, _y: &str) -> String {//we need to return a reference to the value
    let result = String::from("really long string");
    result
}

//Lifetime Elision
//The compiler uses three rules to figure out what lifetimes references have when there aren’t explicit annotations.
//The first rule applies to input lifetimes, and the second and third rules apply to output lifetimes.
//If the compiler gets to the end of the three rules and there are still references for which it can’t figure out lifetimes, the compiler will stop with an error.

//1. Each parameter that is a reference gets its own lifetime parameter.
//2. If there is exactly one input lifetime parameter, that lifetime is assigned to all output lifetime parameters: fn foo<'a>(x: &'a i32) -> &'a i32.
//3. If there are multiple input lifetime parameters, but one of them is &self or &mut self because this is a method, the lifetime of self is assigned to all output lifetime parameters.

fn _first_word(s: &str) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

fn _longest_with_an_announcement<'a, T>(
    x: &'a str,
    y: &'a str,
    ann: T,
) -> &'a str 
    where T: Display
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

你可能感兴趣的:(笔记,rust)