当一个对象可能实现多个特征时,如何创建特征引用结构?

时间:2017-08-06 16:56:32

标签: rust mutability borrowing

我有一个管理多个传感器的结构。我有陀螺仪,加速度计,磁力计,气压计和温度计。所有这些都是特质。

pub struct SensorManager {
    barometer: Barometer + Sized,
    thermometer: Thermometer + Sized,
    gyroscope: Gyroscope + Sized,
    accelerometer: Accelerometer + Sized,
    magnetometer: Magnetometer + Sized
}

我需要将其模块化,以便在配置文件中指定您正在使用的传感器。

问题是某些传感器重叠。例如:一个人可以拥有一个LSM9DS0,其中包含陀螺仪,加速度计和磁力计,而另一个人可以拥有一个L3GD20陀螺仪和一个LSM303D加速度计,磁力计。

在C ++中我会存储指针或引用,但我不确定如何在Rust中安全地正确实现它。

简短版本:需要将每个传感器的引用作为此结构的成员。其中一些参考文献具有相同的目的。

1 个答案:

答案 0 :(得分:1)

  

在C ++中,我会存储指针或引用

Rust不是那个外星人。你做同样的事情。主要区别在于Rust阻止您通过两个不同的路径改变一个东西或者有一个悬挂的引用。

回答您的问题有许多潜在解决方案。例如,您没有描述是否需要能够改变传感器或描述传感器是否会比管理器更长,是否涉及线程等等。所有这些都会影响微代码的优化程度可以。

最灵活的解决方案是:

  1. 使用shared ownership,例如RcArc提供的内容。这允许多个东西拥有传感器。

  2. 使用interior mutability,例如RefCellMutex提供的内容。这样就可以在编译时到运行时一次执行单个变异引用。

  3. 使用trait objects建模动态调度,因为在运行时决定使用哪些具体对象。

  4. struct SensorManager {
        barometer: Rc<RefCell<Barometer>>,
        thermometer: Rc<RefCell<Thermometer>>,
        gyroscope: Rc<RefCell<Gyroscope>>,
    }
    
    impl SensorManager {
        fn new(
            barometer: Rc<RefCell<Barometer>>,
            thermometer: Rc<RefCell<Thermometer>>,
            gyroscope: Rc<RefCell<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.clone(), gyro.clone());
    
        manager.dump_info();
        manager.update();
    }
    

    Complete example on the Playground

    barometer: Barometer + Sized,
    

    你真的不想这样做。 Barometer既是特质又是类型,但类型没有大小。它总是需要在指针后面引用(&BarometerBox<Barometer>RefCell<Barometer>等。)