ฉันกำลังเขียนโปรแกรมจำลองเหตุการณ์ที่ไม่ต่อเนื่องซึ่งจำลองกระบวนการ แลกเปลี่ยนกิจกรรม กระบวนการเป็นการนำกระบวนการลักษณะไปใช้ และจัดเก็บไว้ในคลาสการจำลอง ซึ่งจะบอกให้ทราบเมื่อต้องประมวลผลเหตุการณ์

การจำลองสามารถประกอบด้วยกระบวนการได้เพียงประเภทเดียวเท่านั้น หรือสามารถมีกระบวนการประเภทต่าง ๆ ได้ นี่คือเหตุผลที่ฉันต้องการอิสระในการเลือกกระบวนการแบบไดนามิก

ตอนนี้ฉันทำด้วยกล่อง ทุกรหัสที่ใช้การจำลองจำเป็นต้องสร้างกล่องและใส่วัตถุที่สร้างขึ้นในกล่อง

trait Process {
    // methods
    fn start();
    fn process_event();
}

struct Simulation {
    processes: Vec<dyn Process>
}

impl Simulation {
    fn add_process(&mut self, p: Box<dyn Process>) {
        processes.push(p);
    }
    
    fn run() {
        // calls process_event on processes, based on simulation logic
    }
}

ปัญหาที่ใหญ่ที่สุดของฉันคือในบางกรณีกระบวนการเหล่านี้จำเป็นต้องมีการอ้างอิงตนเอง จากนั้นฉันต้องแทนที่กล่องด้วย Pin หรือ OwningRef และฉันไม่ต้องการให้มีการจำลองที่เป็นไปได้ทั้งหมด สร้าง Pin หรือ OwningRef ดังนั้น ฉันต้องการให้พารามิเตอร์ทั่วไปบางประเภทบอกให้การจำลองใช้คลาสต่างๆ สำหรับกล่อง

ส่วนขยายที่ดีจะต้องไม่มีการจัดส่งแบบไดนามิกเลย และการจำลองมีประเภทกระบวนการจริง ไม่ใช่แบบทั่วไป

ดังนั้นฉันต้องการบางอย่างเช่น - Simulation<P> where P is either a Process or Deref<Process>.

ตอบ

ทั้งสองรุ่นของยาสามัญSimulationเป็นไปได้

  1. มีตัวชี้อัจฉริยะไปยังกระบวนการ ( สนามเด็กเล่น ):
trait Process {}
struct P {}
impl Process for P {}

struct Simulation<T: std::ops::Deref<Target = dyn Process> + Sized> {
    processes: Vec<T>
}

impl<T: std::ops::Deref<Target = dyn Process> + Sized> Simulation<T> {
    fn add_process(&mut self, p: T) {
        self.processes.push(p);
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation<Box<dyn Process>> = Simulation { processes: vec![] };
    s.add_process(Box::new(P {}));
    s.run();
    
    let mut s: Simulation<std::rc::Rc<dyn Process>> = Simulation { processes: vec![] };
    s.add_process(std::rc::Rc::new(P {}));
    s.run();
}
  1. มีประเภทกระบวนการจริง ( สนามเด็กเล่น ):
trait Process {}
struct P {}
impl Process for P {}

struct P2 {}
impl Process for P2 {}

struct Simulation<T: Process> {
    processes: Vec<T>
}

impl<T: Process> Simulation<T> {
    fn add_process(&mut self, p: T) {
        self.processes.push(p);
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation<P> = Simulation { processes: vec![] };
    s.add_process(P {});
    s.run();
    
    let mut s: Simulation<P2> = Simulation { processes: vec![] };
    s.add_process(P2 {});
    s.run();
}
  1. คุณยังสามารถมีการจำลองประเภทหนึ่งซึ่งมีกระบวนการประเภทต่างๆ ( Playground ):
trait Process {}
struct P {}
impl Process for P {}

struct P2 {}
impl Process for P2 {}

struct Simulation {
    processes: Vec<Box<dyn Process>>
}

impl Simulation {
    fn add_process<T: Process + 'static>(&mut self, p: T) {
        self.processes.push(Box::new(p));
    }
    
    fn run(&self) {
        // calls process_event on processes, based on simulation logic
    }
}

fn main() {
    let mut s: Simulation = Simulation { processes: vec![] };
    s.add_process(P {});
    s.run();
    
    let mut s: Simulation = Simulation { processes: vec![] };
    s.add_process(P2 {});
    s.run();
}