美文网首页
rust 面向对象

rust 面向对象

作者: xiongzenghui | 来源:发表于2018-08-12 17:44 被阅读263次

    1、struct 成员变量与成员方法分离

    eg1

    // 结构体的【成员变量】
    struct Foo {
      age: i32,
      name: String,
    }
    
    // 结构体的【成员方法】
    impl Foo {
      fn show(&self) {
        println!("age = {:?}, name = {:?}", self.age, self.name);
      }
    }
    
    fn main()
    {
      let f = Foo {age:99, name:String::from("xiong")};
      f.show();
    }
    
    ➜  main make
    rustc main.rs
    ./main
    age = 99, name = "xiong"
    ➜  main
    

    eg2

    struct Circle {
      x: f64,
      y: f64,
      radius: f64,
    }
    
     /**
      * impl关键字在struct、enum或者trait对象上实现方法调用语法
      * 关联函数 (associated function) 的第一个参数通常为self参数。
      * 
      * 有3种变体:
      * => self,允许实现者移动和修改对象,对应的闭包特性为FnOnce
      * => &self,既不允许实现者移动对象也不允许修改,对应的闭包特性为Fn
      * => &mut self,允许实现者修改对象但不允许移动,对应的闭包特性为FnMut
      * => 不含self参数的关联函数称为静态方法 (static method)
     */
    impl Circle {
      /**
       * 相当于类方法 => Circle::new() 调用 
       */
      fn new(x: f64, y: f64, radius: f64) -> Circle {
        // 创建Circle对象,省去return
        Circle {
          x: x,
          y: y,
          radius: radius,
        }
      }
    
      /**
       * 相当于实例方法 => Circle对象.area()
       */
      fn area(&self) -> f64 {
        self.x * self.y * self.radius
      }
    }
    
    fn main() {
      let c = Circle::new(1.0, 2.0, 3.0); // 堆区申请空间来存储对象数据
      println!("{}", c.area());
    }
    
    ➜  main make
    rustc main.rs
    ./main
    6
    ➜  main
    

    2、接口与实现

    1. 接口定义与实现

    // 接口
    trait HasArea {
      fn area(&self) -> f64;
    }
    
    // 具体类
    struct Rect {
      width: f64,
      height: f64,
    }
    
    // 让【具体类】实现【接口】
    impl HasArea for Rect {
      fn area(&self) -> f64 {
        (self.width * self.height) // 作为返回值 => 必须使用 () 括起来,并不能写 ; 
      }
    }
    
    fn main()
    {
      let r = Rect {width:10.5, height:20.5};
      println!("area = {:?}", r.area());
    }
    
    ➜  main make
    rustc main.rs
    ./main
    area = 215.25
    ➜  main
    

    2. 函数参数针对接口类型

    1. fn run< T: HasArea>(r : &T);

    // 接口
    trait HasArea {
      fn area(&self) -> f64;
    }
    
    // 具体类
    struct Rect {
      width: f64,
      height: f64,
    }
    
    // 让【具体类】实现【接口】
    impl HasArea for Rect {
      fn area(&self) -> f64 {
        (self.width * self.height) // 作为返回值 => 必须使用 () 括起来,并不能写 ; 
      }
    }
    
    // 全局函数 => 参数类型为接口类型
    fn run<T: HasArea>(r : &T) {
      println!("area = {:?}", r.area());
    }
    
    fn main()
    {
      let r = Rect {width:10.5, height:20.5};
      run(&r);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    area = 215.25
    ➜  main
    

    2. fn < T>(r : &T) where T: HasArea;

    // 接口
    trait HasArea {
      fn area(&self) -> f64;
    }
    
    // 具体类
    struct Rect {
      width: f64,
      height: f64,
    }
    
    // 让【具体类】实现【接口】
    impl HasArea for Rect {
      fn area(&self) -> f64 {
        (self.width * self.height) // 作为返回值 => 必须使用 () 括起来,并不能写 ; 
      }
    }
    
    // 全局函数 => 参数类型为接口类型
    // fn run<T: HasArea>(r : &T) {
    //   println!("area = {:?}", r.area());
    // }
    fn run<T>(r : &T) where T: HasArea
    {
      println!("area = {:?}", r.area());
    }
    
    fn main()
    {
      let r = Rect {width:10.5, height:20.5};
      run(&r);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    area = 215.25
    ➜  main
    

    3. where 使用

    // 接口1
    trait Man {
      fn name(&self) -> String;
    }
    
    // 接口2
    trait Animal {
      fn name(&self) -> String;
    }
    
    // 接口3
    trait Runnable {
      fn run(&self);
    }
    
    fn make_pair<T, U>(a: T, b: U) -> (T, U) 
      where T: Man, 
            U: Animal + Runnable // 模板参数U必须实现两个接口
    {
      (a, b)
    }
    
    fn main()
    {}
    

    4. 使用系统接口

    use std::fmt::Debug;
    
    fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
        x.clone();
        y.clone();
        println!("{:?}", y);
    }
    
    fn bar<T, K>(x: T, y: K)
        where T: Clone,
              K: Clone + Debug
    {
        x.clone();
        y.clone();
        println!("{:?}", y);
    }
    

    3. 接口中可以带有方法默认实现

    trait Foo {
      fn foo(&self);
      
      // default method
      fn bar(&self) { println!("We called bar."); }
    }
    
    struct Baz;
    
    impl Foo for Baz {
      fn foo(&self) { println!("foo"); }
    }
    
    fn main()
    {
      let b = Baz{};
      b.bar();
    }
    
    ➜  main make
    rustc main.rs
    ./main
    We called bar.
    ➜  main
    

    4. 接口的继承

    trait Foo {
      fn foo(&self);
      
      // default method
      fn foobar(&self) { println!("Foo::foobar()"); }
    }
    
    // 接口继承
    trait FooBar : Foo {
      fn foobar(&self);
    }
    
    struct Baz;
    
    impl Foo for Baz {
      fn foo(&self) { println!("foo"); }
    }
    
    impl FooBar for Baz {
      fn foobar(&self) { println!("FooBar::foobar()"); }
    }
    
    fn main()
    {
      let b = Baz{};
      
      // 调用不同接口的实现
      Foo::foobar(&b);
      FooBar::foobar(&b);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    Foo::foobar()
    FooBar::foobar()
    ➜  main
    

    5、运算符重载

    1. 重载 + 操作符

    use std::ops::Add;
    
    #[derive(Debug)]
    struct Point {
      x: i32,
      y: i32,
    }
    
    // 给struct重载+运算符
    impl Add for Point {
      // 1. 确定模板参数的具体数据类型
      type Output = Point;
    
      // 2. +运算符重载函数实现
      fn add(self, other: Point) -> Point {
        Point { x: self.x + other.x, y: self.y + other.y }
      }
    }
    
    fn main() {
      let p1 = Point { x: 1, y: 0 };
      let p2 = Point { x: 2, y: 3 };
      let p3 = p1 + p2;
      println!("{:?}", p3);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    Point { x: 3, y: 3 }
    ➜  main
    

    其他运算符重载套路相似。

    2. 实现 Deref<Target=T>接口,则 *T 返回 &T类型的值

    use std::ops::Deref;
    
    // 实体类
    struct Animal<T> {
      value: T, // 成员value
    }
    
    // 实现 Deref<Target=T>,*对象 => 返回自定义的值
    impl<T> Deref for Animal<T> {
      // 1. 使用【预定义】模板参数Target指定deref()的返回值类型
      type Target = T;
    
      // 2. 实现deref()
      fn deref(&self) -> &T {
        return &self.value // 返回转换成的结果值
      }
    }
    
    fn main() {
      let anim = Animal { value: "monkey" };
      println!("{}", *anim == "monkey");
      println!("{}", *anim);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    true
    monkey
    ➜  main
    

    3. 实现 Deref<Target=T>接口,&U 的值自动强制转换为 &T 类型

    use std::rc::Rc;
    
    fn foo(s: &str) {
      // borrow a string for a second
    }
    
    fn main()
    {
      // String implements Deref<Target=str>
      let owned = "Hello".to_string();
    
      // Rc 实现了 Deref<Target=T> 接口
      // => &Rc对象,返回 &T
      let counted = Rc::new(owned);
    
      // therefore, this works:
      foo(&counted);
    }
    
    ➜  main make
    rustc main.rs
    ./main
    ➜  main
    

    4. &U 的多重嵌套

    struct Foo;
    
    impl Foo {
      fn foo(&self) { println!("Foo() ..."); }
    }
    
    fn main()
    {
      let f = Foo;
      f.foo();
      (&f).foo();
      (&&f).foo();
      (&&&&&&&&f).foo();
    }
    
    ➜  main make
    rustc main.rs
    ./main
    Foo() ...
    Foo() ...
    Foo() ...
    Foo() ...
    ➜  main
    

    相关文章

      网友评论

          本文标题:rust 面向对象

          本文链接:https://www.haomeiwen.com/subject/pyasbftx.html