• Rust语言学习笔记(10)


    特质(高级)

    // 相关类型
    pub trait Iterator {
        type Item;
        fn next(&mut self) -> Option<Self::Item>;
    }
    impl Iterator for Counter {
        type Item = u32;
        fn next(&mut self) -> Option<Self::Item> {
    
    // 缺省类型参数
    trait Add<RHS=Self> {
        type Output;
        fn add(self, rhs: RHS) -> Self::Output;
    }
    // 操作符重载
    use std::ops::Add;
    #[derive(Debug, PartialEq)]
    struct Point {
        x: i32,
        y: i32,
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, other: Point) -> Point {
            Point {
                x: self.x + other.x,
                y: self.y + other.y,
            }
        }
    }
    fn main() {
        assert_eq!(Point { x: 1, y: 0 } + Point { x: 2, y: 3 },
                   Point { x: 3, y: 3 });
    }
    // 覆盖缺省类型参数
    use std::ops::Add;
    struct Millimeters(u32);
    struct Meters(u32);
    impl Add<Meters> for Millimeters {
        type Output = Millimeters;
        fn add(self, other: Meters) -> Millimeters {
            Millimeters(self.0 + (other.0 * 1000))
        }
    }
    
    trait Pilot {
        fn fly(&self);
    }
    trait Wizard {
        fn fly(&self);
    }
    struct Human;
    impl Pilot for Human {
        fn fly(&self) {
            println!("This is your captain speaking.");
        }
    }
    impl Wizard for Human {
        fn fly(&self) {
            println!("Up!");
        }
    }
    impl Human {
        fn fly(&self) {
            println!("*waving arms furiously*");
        }
    }
    // 区分同名方法
    fn main() {
        let person = Human;
        Pilot::fly(&person);
        Wizard::fly(&person);
        person.fly();
    }
    /*
    This is your captain speaking.
    Up!
    *waving arms furiously*
    */
    
    trait Animal {
        fn baby_name() -> String;
    }
    struct Dog;
    impl Dog {
        fn baby_name() -> String {
            String::from("Spot")
        }
    }
    impl Animal for Dog {
        fn baby_name() -> String {
            String::from("puppy")
        }
    }
    // 区分同名方法
    fn main() {
        println!("A baby dog is called a {}", Dog::baby_name());
        println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
    }
    /*
    A baby dog is called a Spot
    A baby dog is called a puppy
    */
    
    // 某个特质的实现依赖于另一个特质的实现
    // 超特质(Supertraits)
    use std::fmt;
    trait OutlinePrint: fmt::Display {
        fn outline_print(&self) {
            let output = self.to_string();
            let len = output.len();
            println!("{}", "*".repeat(len + 4));
            println!("*{}*", " ".repeat(len + 2));
            println!("* {} *", output);
            println!("*{}*", " ".repeat(len + 2));
            println!("{}", "*".repeat(len + 4));
        }
    }
    // 需要实现超特质及其所依赖的特质
    struct Point {
        x: i32,
        y: i32,
    }
    impl OutlinePrint for Point {}
    use std::fmt;
    impl fmt::Display for Point {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "({}, {})", self.x, self.y)
        }
    }
    
    // 通过元组单元类型来实现新类型(newtype)范式
    // 无法为 Vec 实现 Display (因为两者都是外部类型)
    // 但是可以为 Wrapper 实现 Display
    use std::fmt;
    struct Wrapper(Vec<String>);
    impl fmt::Display for Wrapper {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "[{}]", self.0.join(", "))
        }
    }
    fn main() {
        let w = Wrapper(vec![String::from("hello"), String::from("world")]);
        println!("w = {}", w);
    }
    

    类型(高级)

    // 类型别名
    type Kilometers = i32;
    let x: i32 = 5;
    let y: Kilometers = 5;
    println!("x + y = {}", x + y);
    // 类型别名
    type Thunk = Box<dyn Fn() + Send + 'static>;
    let f: Thunk = Box::new(|| println!("hi"));
    fn takes_long_type(f: Thunk) {
    }
    fn returns_long_type() -> Thunk {
    }
    // 类型别名
    type Result<T> = std::result::Result<T, std::io::Error>;
    pub trait Write {
        fn write(&mut self, buf: &[u8]) -> Result<usize>;
        fn flush(&mut self) -> Result<()>;
        fn write_all(&mut self, buf: &[u8]) -> Result<()>;
        fn write_fmt(&mut self, fmt: Arguments) -> Result<()>;
    }
    

    函数和闭包(高级)

    // 函数指针类型 fn
    fn add_one(x: i32) -> i32 {
        x + 1
    }
    fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
        f(arg) + f(arg)
    }
    fn main() {
        let answer = do_twice(add_one, 5);
        println!("The answer is: {}", answer);
    }
    
    // 用函数指针来替代闭包
    let list_of_numbers = vec![1, 2, 3];
    let list_of_strings: Vec<String> = list_of_numbers
        .iter()
        .map(ToString::to_string) // .map(|i| i.to_string())
        .collect();
    
    // 用函数指针来替代闭包
    enum Status {
        Value(u32),
        Stop,
    }
    let list_of_statuses: Vec<Status> =
        (0u32..20)
        .map(Status::Value)
        .collect();
    
    // 不能直接返回闭包
    // 出错信息 Fn 特质的大小不定
    fn returns_closure() -> Fn(i32) -> i32 {
        |x| x + 1 // error
    }
    // 返回闭包的指针
    fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
       Box::new(|x| x + 1)
    }
    

    panic

    fn main() {
        panic!("crash and burn");
    }
    /*
    $ cargo run
    thread 'main' panicked at 'crash and burn', src/main.rs:2:5
    */
    
    fn main() {
        let v = vec![1, 2, 3];
        v[99];
    }
    /*
    $ cargo run
    thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2806:10
    $ RUST_BACKTRACE=1 cargo run
    thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2806:10
    stack backtrace:
       0: backtrace::backtrace::libunwind::trace
                 at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
    ...
      17: panic::main
                 at src/main.rs:3
    ...
      26: panic::main
    */
    

    Result<T, E>

    use std::fs::File;
    fn main() {
        let f = File::open("hello.txt");
        let f = match f {
            Ok(file) => file,
            Err(error) => panic!("Problem opening the file: {:?}", error),
        };
    }
    /*
    $ cargo run
    thread 'main' panicked at 'Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:6:23
    */
    
    use std::fs::File;
    use std::io::ErrorKind;
    fn main() {
        let f = File::open("hello.txt");
        let f = match f {
            Ok(file) => file,
            Err(error) => match error.kind() {
                ErrorKind::NotFound => match File::create("hello.txt") {
                    Ok(fc) => fc,
                    Err(e) => panic!("Problem creating the file: {:?}", e),
                },
                other_error => {
                    panic!("Problem opening the file: {:?}", other_error)
                }
            },
        };
    }
    
    use std::fs::File;
    use std::io::ErrorKind;
    fn main() {
        let f = File::open("hello.txt").unwrap_or_else(|error| {
            if error.kind() == ErrorKind::NotFound {
                File::create("hello.txt").unwrap_or_else(|error| {
                    panic!("Problem creating the file: {:?}", error);
                })
            } else {
                panic!("Problem opening the file: {:?}", error);
            }
        });
    }
    
    use std::fs::File;
    fn main() {
        let f = File::open("hello.txt").unwrap();
    }
    /*
    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 2, message: "No such file or directory" } }', src/libcore/result.rs:906:4
    */
    
    use std::fs::File;
    fn main() {
        let f = File::open("hello.txt").expect("Failed to open hello.txt");
    }
    /*
    thread 'main' panicked at 'Failed to open hello.txt: Error { repr: Os { code: 2, message: "No such file or directory" } }', src/libcore/result.rs:906:4
    */
    

    ? 操作符

    use std::fs::File;
    use std::io;
    use std::io::Read;
    fn read_username_from_file() -> Result<String, io::Error> {
        let f = File::open("hello.txt");
        let mut f = match f {
            Ok(file) => file,
            Err(e) => return Err(e),
        };
        let mut s = String::new();
        match f.read_to_string(&mut s) {
            Ok(_) => Ok(s),
            Err(e) => Err(e),
        }
    }
    
    use std::fs::File;
    use std::io;
    use std::io::Read;
    fn read_username_from_file() -> Result<String, io::Error> {
        let mut f = File::open("hello.txt")?;
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    }
    
    use std::fs::File;
    use std::io;
    use std::io::Read;
    fn read_username_from_file() -> Result<String, io::Error> {
        let mut s = String::new();
        File::open("hello.txt")?.read_to_string(&mut s)?;
        Ok(s)
    }
    
    use std::fs;
    use std::io;
    fn read_username_from_file() -> Result<String, io::Error> {
        fs::read_to_string("hello.txt")
    }
    
    use std::error::Error;
    use std::fs::File;
    fn main() -> Result<(), Box<dyn Error>> {
        let f = File::open("hello.txt")?;
        Ok(())
    }
    
  • 相关阅读:
    《C++ Primer》学习笔记第2章 变量和基本类型
    Java学习笔记类的继承与多态特性
    Java的冒泡排序问题
    新起点,分享,进步
    MVC2中Area的路由注册实现
    了解一下new关键字实现阻断继承的原理
    利用Bing API开发的搜索工具(MVC+WCF)
    ASP.NET MVC中错误处理方式
    const和readonly内部区别
    WCF中校验参数的实现方式(一)
  • 原文地址:https://www.cnblogs.com/zwvista/p/12742634.html
Copyright © 2020-2023  润新知