代码之家  ›  专栏  ›  技术社区  ›  ruipacheco

为什么我的第二个方法需要是可变的?

  •  -1
  • ruipacheco  · 技术社区  · 4 年前

    如果结构的字段是私有的,是否可以借用结构的一部分作为可变的,另一部分作为不可变的。

    fn main() {
        let mut ecs = EntityComponentSystem::new();
    
        for e_id in ecs.get_entities_with_component::<Velocity>().unwrap() {
               let components = ecs.get_mut_components(e_id);
               ...
    }
    
    impl EntityComponentSystem {
        ...
        pub fn get_entities_with_component<K: Key>(&self) -> Option<&HashSet<u64>> {
            self.entities_with_components.get(&TypeId::of::<K>())
        }
    
        pub fn get_mut_components(&mut self, entity_id: u64) -> &mut TypeMap {
            let entity = self.entities.get_mut(&entity_id).unwrap();
            &mut entity.components
        }
    }
    
    pub struct EntityComponentSystem {
        entities: HashMap<u64, Entity>,                     <------- I would like to modify this.
        entities_with_components: HashMap<TypeId, HashSet<u64>>,   <---- while reading from this!
    }
    

    编译器给了我:

    error[E0502]: cannot borrow `*ecs` as mutable because it is also borrowed as immutable
      --> physics.rs:19:26
       |
    18 |     for e_id in ecs.get_entities_with_component::<Velocity>() {
       |                 --- immutable borrow occurs here
    19 |         let components = ecs.get_mut_components(*e_id);
       |                          ^^^ mutable borrow occurs here
    ...
    26 |     }
       |     - immutable borrow ends here
    

    我不明白的是 &self 参考 get_entities_with_component 在我们基本上归还了一部分后,它仍然是借来的 entities_with_components 现场。

    难道不应该只借用那部分吗?有什么办法可以强制执行吗?

    0 回复  |  直到 7 年前
        1
  •  8
  •   Shepmaster Tim Diekmann    5 年前

    您只能借用 整个的 struct是不可变的或可变的,没有只借用它的一部分的概念。当这成为一个问题时,你可以使用 interior mutability 以a的形式 RefCell :

    pub struct EntityComponentSystem {
        entities: RefCell<HashMap<u64, Entity>>,
        entities_with_components: HashMap<TypeId, HashSet<u64>>,
    }
    

    现在,您可以将整个结构体作为不可变结构体借用,并借用 RefCell 独立为可变:

    pub fn get_mut_components(&self, entity_id: u64) -> &mut TypeMap {
        let mut entities = self.entities.borrow_mut();
        let entity = entities.get_mut(&entity_id).unwrap();
        &mut entity.components
    }
    
        2
  •  2
  •   red75prime    7 年前

    不,函数不能返回对结构的一部分的引用,并使结构部分借用。

    然而,你可以像这样返回不可变和可变借用的元组

    #[derive(Debug)]
    struct AB(u32, u32);
    
    impl AB {
        fn borrow_parts(&mut self) -> (&u32, &mut u32) {
            (&self.0, &mut self.1)
        }
    }
    
    fn main() {
        let mut ab = AB(0, 2);
        {
            let (a, b) = ab.borrow_parts();
            *b = *a;
        }
        println!("{:?}", ab);
    }