在 C++ 中,我会存储指针或引用
Rust 并不是那么陌生。你做同样的事情。主要区别在于,Rust 阻止您通过两条不同的路径改变一件事或让引用悬空。
回答您的问题有许多潜在的解决方案。例如,您没有描述是否需要能够改变传感器或描述传感器是否会比管理器寿命更长,是否会涉及线程等。所有这些都会影响代码的微优化程度.
最灵活的解决方案是:
使用共享所有权,例如由Rc
or提供的所有权Arc
。这允许多个事物拥有传感器。
使用内部可变性,例如RefCell
or提供的Mutex
。这将一次执行单个变异引用从编译时移动到运行时。
使用trait 对象来模拟动态调度,因为在运行时决定使用哪些具体对象。
use std::{cell::RefCell, rc::Rc};
trait Barometer {
fn get(&self) -> i32;
fn set(&self, value: i32);
}
trait Thermometer {
fn get(&self) -> i32;
fn set(&self, value: i32);
}
trait Gyroscope {
fn get(&self) -> i32;
fn set(&self, value: i32);
}
struct Multitudes;
impl Barometer for Multitudes {
fn get(&self) -> i32 {
1
}
fn set(&self, value: i32) {
println!("Multitudes barometer set to {}", value)
}
}
impl Thermometer for Multitudes {
fn get(&self) -> i32 {
2
}
fn set(&self, value: i32) {
println!("Multitudes thermometer set to {}", value)
}
}
struct AutoGyro;
impl Gyroscope for AutoGyro {
fn get(&self) -> i32 {
3
}
fn set(&self, value: i32) {
println!("AutoGyro gyroscope set to {}", value)
}
}
struct SensorManager {
barometer: Rc<RefCell<dyn Barometer>>,
thermometer: Rc<RefCell<dyn Thermometer>>,
gyroscope: Rc<RefCell<dyn Gyroscope>>,
}
impl SensorManager {
fn new(
barometer: Rc<RefCell<dyn Barometer>>,
thermometer: Rc<RefCell<dyn Thermometer>>,
gyroscope: Rc<RefCell<dyn Gyroscope>>,
) -> Self {
Self {
barometer,
thermometer,
gyroscope,
}
}
fn dump_info(&self) {
let barometer = self.barometer.borrow();
let thermometer = self.thermometer.borrow();
let gyroscope = self.gyroscope.borrow();
println!(
"{}, {}, {}",
barometer.get(),
thermometer.get(),
gyroscope.get()
);
}
fn update(&self) {
self.barometer.borrow_mut().set(42);
self.thermometer.borrow_mut().set(42);
self.gyroscope.borrow_mut().set(42);
}
}
fn main() {
let multi = Rc::new(RefCell::new(Multitudes));
let gyro = Rc::new(RefCell::new(AutoGyro));
let manager = SensorManager::new(multi.clone(), multi, gyro);
manager.dump_info();
manager.update();
}
操场上的完整示例
barometer: Barometer + Sized,
你真的不想这样做。Barometer
既是trait又是type,但 type 没有大小。它总是需要在指针后面引用(&Barometer
, Box<Barometer>
,RefCell<Barometer>
等)
也可以看看: