2015-06-06 4 views
7

निम्नलिखित एक क्षेत्र के साथ एक साधारण सिमुलेशन है जो आयताकार क्षेत्र है जिसमें दो गेंदें इसके चारों ओर उछालती हैं। Field संरचना में update विधि है, जो प्रत्येक गेंद पर update पर कॉल करती है। गेंदें, update विधि में, अपने वेग के आधार पर चारों ओर स्थानांतरित करने की आवश्यकता है। लेकिन वे भी, साथ ही क्षेत्र .:स्वामित्व वाली ऑब्जेक्ट की विधि के लिए उत्परिवर्तनीय आत्म संदर्भ पास करना

fn main() { 
    let mut field = Field::new(Vector2d { x: 100, y: 100 }); 
    field.update(); 
} 

#[derive(Copy, Clone)] 
struct Vector2d { 
    x: i32, 
    y: i32, 
} 

struct Ball { 
    radius: i32, 
    position: Vector2d, 
    velocity: Vector2d, 
} 

impl Ball { 
    fn new(radius: i32, position: Vector2d, velocity: Vector2d) -> Ball { 
     Ball { 
      radius: radius, 
      position: position, 
      velocity: velocity, 
     } 
    } 

    fn update(&mut self, field: &Field) { 
     // check collisions with walls 
     // and other objects 
    } 
} 

struct Field { 
    size: Vector2d, 
    balls: [Ball; 2], 
} 

impl Field { 
    fn new(size: Vector2d) -> Field { 
     let position_1 = Vector2d { 
      x: size.x/3, 
      y: size.y/3, 
     }; 
     let velocity_1 = Vector2d { x: 1, y: 1 }; 
     let position_2 = Vector2d { 
      x: size.x * 2/3, 
      y: size.y * 2/3, 
     }; 
     let velocity_2 = Vector2d { x: -1, y: -1 }; 

     let ball_1 = Ball::new(1, position_1, velocity_1); 
     let ball_2 = Ball::new(1, position_2, velocity_2); 

     Field { 
      size: size, 
      balls: [ball_1, ball_2], 
     } 
    } 

    fn update(&mut self) { 
     // this does not compile 
     self.balls[0].update(self); 
     self.balls[1].update(self); 
    } 
} 

की सीमाओं मैं सीमाओं और Ball struct के अद्यतन कार्य करने के लिए अन्य गेंद के बारे में जानकारी कैसे प्राप्त करूं एक दूसरे से प्रतिक्रिया करने के लिए की जरूरत है? Field::update में ये लाइनें संकलन नहीं:

self.balls[0].update(self); 
self.balls[1].update(self); 

निम्न त्रुटि देते:

error[E0502]: cannot borrow `*self` as immutable because `self.balls[..]` is also borrowed as mutable 
    --> src/main.rs:62:30 
    | 
62 |   self.balls[0].update(self); 
    |   -------------  ^^^^- mutable borrow ends here 
    |   |     | 
    |   |     immutable borrow occurs here 
    |   mutable borrow occurs here 

जो मैं समझता हूँ, लेकिन मैं इस के आसपास पाने के लिए पता नहीं है।

उत्तर

6

वर्तमान में Ball संरचना को Field के बारे में जानने की आवश्यकता है, यह स्वयं को अपडेट करने में सक्षम है। यह संकलित नहीं होता है क्योंकि परिणाम उत्परिवर्तन के साथ संयुक्त चक्रीय संदर्भ होगा। आप Cell या RefCell (बाद में प्रदर्शन लागत वाले) का उपयोग करके यह काम कर सकते हैं लेकिन कोड को अलग-अलग संरचना करना बेहतर होगा। Field संरचना Ball - Ball और Ball - Wall टकराव के लिए संरचना जांचें और हल करें। Ball संरचना का update फ़ंक्शन Ball की स्थिति को अपडेट करने में संभाल सकता है।

// Ball's update function 
fn update(&mut self) { 
    // update position 
} 

// Field's update function 
fn update(&mut self) { 
    for ball in self.balls.iter_mut() { 
     ball.update(); 
    } 

    // check for collisions 

    // resolve any collisions 
} 
+1

हाँ,: आप आसानी से/सस्ते में एक Ball कर सकते हैं, जगह का प्रयास करें:

use std::mem; struct Ball { size: u8, } impl Ball { fn update(&mut self, field: &Field) {} } impl Default for Ball { fn default() -> Ball { Ball { size: 0 } } } struct Field { ball: Ball, } impl Field { fn update(&mut self) { let mut ball = mem::replace(&mut self.ball, Ball::default()); ball.update(self); self.ball = ball; } } 

आप आसानी से एक नहीं कर सकते हैं, तो आप एक Option और take उपयोग कर सकते हैं । मैन, जंग वास्तव में मुझे प्रोग्राम के तरीके के बारे में अलग-अलग सोचने के लिए तैयार कर रहा है। –

1

यहाँ एक छोटे उदाहरण है:

struct Ball { 
    size: u8, 
} 

impl Ball { 
    fn update(&mut self, field: &Field) {} 
} 

struct Field { 
    ball: Ball, 
} 

impl Field { 
    fn update(&mut self) { 
     self.ball.update(self) 
    } 
} 

जड़ समस्या यह है कि जब आप Field के लिए एक संदर्भ में पारित, आप गारंटी नहीं है कि Field (नहीं बदल सकते हैं अपरिवर्तनीय का हिस्सा बना रहे हैं है "अपरिवर्तनीय संदर्भ")। हालांकि, आप इसके एक हिस्से को बदलने का भी प्रयास कर रहे हैं: गेंद! Ball::update के कार्यान्वयन में कौन सा संदर्भ आधिकारिक, self या field होना चाहिए?

एक समाधान संरचना update के लिए आवश्यक के अलग अलग हिस्सों है और उन नहीं और से पहले उन्हें का उपयोग update फ़ंक्शन कॉल:

struct Ball { 
    size: u8, 
} 

impl Ball { 
    fn update(&mut self, field: &u8) {} 
} 

struct Field { 
    players: u8, 
    ball: Ball, 
} 

impl Field { 
    fn update(&mut self) { 
     self.ball.update(&self.players) 
    } 
} 

तुम भी एक साफ पैकेज में इन टुकड़ों संदर्भ ऊपर बंडल कर सकते हैं :

struct Ball { 
    size: u8, 
} 

impl Ball { 
    fn update(&mut self, field: BallUpdateInfo) {} 
} 

struct BallUpdateInfo<'a> { 
    players: &'a u8, 
} 

struct Field { 
    players: u8, 
    ball: Ball, 
} 

impl Field { 
    fn update(&mut self) { 
     let info = BallUpdateInfo { players: &self.players }; 
     self.ball.update(info) 
    } 
} 

या अपने युक्त struct पुनर्गठन शुरू से ही जानकारी को अलग करने के:

+०१२३५१६४१०६
struct Ball { 
    size: u8, 
} 

impl Ball { 
    fn update(&mut self, field: &UpdateInfo) {} 
} 

struct UpdateInfo { 
    players: u8, 
} 

struct Field { 
    update_info: UpdateInfo, 
    ball: Ball, 
} 

impl Field { 
    fn update(&mut self) { 
     self.ball.update(&self.update_info) 
    } 
} 

तुम भी अन्य तरह से जाने के लिए और यह करने के लिए किसी भी परिवर्तन करने से पहले Field से Ball को दूर कर सकता है।कि काम करेंगे

struct Ball { 
    size: u8, 
} 

impl Ball { 
    fn update(&mut self, field: &Field) {} 
} 

struct Field { 
    ball: Option<Ball>, 
} 

impl Field { 
    fn update(&mut self) { 
     if let Some(mut ball) = self.ball.take() { 
      ball.update(self); 
      self.ball = Some(ball); 
     } 
    } 
} 
संबंधित मुद्दे