特征,生命和容器

时间:2017-08-02 15:13:27

标签: rust traits lifetime

我有两种类型的结构:

  1. Ship具有2D位置和速度
  2. Target站着
  3. 我有一个包含所有Ship s的向量,另一个包含所有Target s的向量。我想知道Ship与另一个ShipTarget发生碰撞,所以我会检查所有船只并检查是否有碰撞。

    我知道这是一堆代码,但我确实想提供一个完整的例子。

    use std::any::Any;
    
    
    trait AsAny {
        fn as_any(&self) -> &Any;
    }
    
    impl<T: Any> AsAny for T {
        fn as_any(&self) -> &Any {
            self
        }
    }
    
    trait AsPoint {
        fn as_point(&self) -> &Point;
    }
    
    impl<T: Point> AsPoint for T {
        fn as_point(&self) -> &Point {
            self
        }
    }
    
    trait Point: AsPoint {
        fn x(&self) -> i32;
        fn y(&self) -> i32;
    
    
        fn distance(&self, rhs: &Point) -> i32 {
            (( ((self.x() - rhs.x()) as f64).powi(2) +
                ((self.y() - rhs.y()) as f64).powi(2)
            )as f64).sqrt().round() as i32
        }
    }
    
    struct Ship {
        x: i32,
        y: i32,
        radius: i32,
        vx: i32,
        vy: i32,
    }
    
    struct Target {
        x: i32,
        y: i32,
        radius: i32,
    }
    
    struct Collision<'a> {
        pub a: &'a mut (Element + 'a),
        pub b: &'a mut (Element + 'a),
    }
    
    trait Element: Point + AsAny {
        fn radius(&self) -> i32;
        fn apply_collision(&mut self, rhs: &mut Element);
    }
    
    impl Point for Target {
        fn x(&self) -> i32 {
            self.x
        }
    
        fn y(&self) -> i32 {
            self.y
        }
    }
    
    impl Point for Ship {
        fn x(&self) -> i32 {
            self.x
        }
    
        fn y(&self) -> i32 {
            self.y
        }
    }
    impl Element for Ship {
        fn apply_collision(&mut self, rhs: &mut Element) {
    
            if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
                self.collision_with_target(as_target);
            } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
                self.collision_with_ship(as_ship);
            }
        }
        fn radius(&self) -> i32 {
            self.radius
        }
    }
    
    impl Element for Target {
        fn radius(&self) -> i32 {
            self.radius
        }
    
        fn apply_collision(&mut self, rhs: &mut Element) {
            match  rhs.as_any().downcast_ref::<Ship>() {
                Some(ref mut as_ship ) => {
                    as_ship.vx = -as_ship.vx;
                    as_ship.vy = -as_ship.vy;
                },
                None => panic!(), // should never happen
            }
        }
    }
    
    impl Ship {
        fn collision_with_target(&mut self, target: &Target) {
            self.vx = -self.vx;
            self.vy = -self.vy;
        }
    
        fn collision_with_ship(&mut self, ship: &mut Ship) {
            let vx = self.vx;
            let vy = self.vy;
    
            self.vx = ship.vx;
            self.vy = ship.vy;
    
            ship.vx = vx;
            ship.vy = vy;
        }
    }
    
    fn collide<'a>(u1: &'a mut Element, u2: &'a mut Element) -> Option<Collision<'a>> {
    
        if u1.as_point().distance(u2.as_point()) < u1.radius() + u2.radius() {
            Some(Collision { a: u1, b: u2 })
        } else {None}
    
    }
    
    fn handle_collisions(ships : &mut Vec<Ship>, targets: &mut Vec<Target>) {
    
        for ship in ships.iter_mut() {
            for other_ship in &mut ships[1..] {
                let collision = collide(ship, other_ship);
    
                if let Some(col) = collision {
                    col.a.apply_collision(col.b);
                }
            }
    
            for target in targets.iter_mut() {
                let collision = collide(ship,target);
    
                if let Some(col) = collision {
                    col.a.apply_collision(col.b);
                }
            }
        }
    }
    fn main() {
        let ships: Vec<Ship> = vec![Ship {
            x: 10,
            y: 10,
            radius: 20,
            vx: 5,
            vy: 5,
        }, Ship {
            x: 20,
            y: 20,
            radius: 10,
            vx: 100,
            vy: 100,
        }];
    
        let targets = vec![ Target{
            x: 15,
            y: 15,
            radius: 10,
        }];
    
    
        handle_collisions(&mut ships, &mut targets);
    }
    

    Here是代码的操场链接。

    编译器输出:

    Compiling playground v0.0.1 (file:///playground)
    error[E0477]: the type `&mut Element` does not fulfill the required lifetime
      --> src/main.rs:84:51
       |
    84 |         } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
       |                                                   ^^^^^^
       |
       = note: type must satisfy the static lifetime
    
    error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
      --> src/main.rs:82:46
       |
    82 |         if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
       |                                              ^^^^^^
       |
    note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 80:5...
      --> src/main.rs:80:5
       |
    80 | /     fn apply_collision(&mut self, rhs: &mut Element) {
    81 | |
    82 | |         if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
    83 | |             self.collision_with_target(as_target);
    ...  |
    86 | |         }
    87 | |     }
       | |_____^
    note: ...so that the reference type `&mut Element` does not outlive the data it points at
      --> src/main.rs:82:42
       |
    82 |         if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
       |                                          ^^^^^^^^^^^^
       = note: but, the lifetime must be valid for the static lifetime...
    note: ...so that the type `&mut Element` will meet its required lifetime bounds
      --> src/main.rs:82:46
       |
    82 |         if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
       |                                              ^^^^^^
    
    error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
      --> src/main.rs:84:51
       |
    84 |         } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
       |                                                   ^^^^^^
       |
    note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 80:5...
      --> src/main.rs:80:5
       |
    80 | /     fn apply_collision(&mut self, rhs: &mut Element) {
    81 | |
    82 | |         if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
    83 | |             self.collision_with_target(as_target);
    ...  |
    86 | |         }
    87 | |     }
       | |_____^
    note: ...so that the reference type `&mut Element` does not outlive the data it points at
      --> src/main.rs:84:47
       |
    84 |         } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
       |                                               ^^^^^^^^^^^^
       = note: but, the lifetime must be valid for the static lifetime...
    note: ...so that the type `&mut Element` will meet its required lifetime bounds
      --> src/main.rs:84:51
       |
    84 |         } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
       |                                                   ^^^^^^
    
    error[E0477]: the type `&mut Element` does not fulfill the required lifetime
      --> src/main.rs:99:20
       |
    99 |         match  rhs.as_any().downcast_ref::<Ship>() {
       |                    ^^^^^^
       |
       = note: type must satisfy the static lifetime
    
    error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
      --> src/main.rs:99:20
       |
    99 |         match  rhs.as_any().downcast_ref::<Ship>() {
       |                    ^^^^^^
       |
    note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 98:5...
      --> src/main.rs:98:5
       |
    98 | /     fn apply_collision(&mut self, rhs: &mut Element) {
    99 | |         match  rhs.as_any().downcast_ref::<Ship>() {
    100| |             Some(ref mut as_ship ) => {
    101| |                 as_ship.vx = -as_ship.vx;
    ...  |
    105| |         }
    106| |     }
       | |_____^
    note: ...so that the reference type `&mut Element` does not outlive the data it points at
      --> src/main.rs:99:16
       |
    99 |         match  rhs.as_any().downcast_ref::<Ship>() {
       |                ^^^^^^^^^^^^
       = note: but, the lifetime must be valid for the static lifetime...
    note: ...so that the type `&mut Element` will meet its required lifetime bounds
      --> src/main.rs:99:20
       |
    99 |         match  rhs.as_any().downcast_ref::<Ship>() {
       |                    ^^^^^^
    

0 个答案:

没有答案